English 中文(简体)
React: Accessed State from Customs Hook Inside event Handler
原标题:React: Accessing Updated State from Custom Hook Inside Event Handler

在复读部分,Im面临一项挑战,即活动手和习俗之间的国家同步。 活动主持人更新了国家变量,我需要获得另一个国家的最新价值,而后者是根据这一最新状况而从习俗中得出的。

我们使用一种习俗,界定国家变量和事件手。

活动手稿将国家变数代码<>a至c(取决于event论据),然后需要使用最新数值b,由习俗所退回,取决于a

function MyComponent(props) {
  const [a, setA] = useState(null);
  const b = useCustomHook(a);

  const eventHandler = useCallback(async (event) => {
    try {
      const c = event.data;

      setA(c);

      if (b) { // we need to use b here, but it is stale (one step behind)
        // logic
      }
      else {
        // more logic
      }
    } catch (e) {
      console.error(`Error:`, e);
    }

  }, [b]);
}

问题是,<条码>b始终是活动手脚的一步。 在发生事件时,其价值尚未更新。

如何在活动手稿中获取<代码>b(取决于a,该编码取决于c,该编码取决于event)的最新价值?

我只试图在事件的手里确定国家变量,并对逻辑的其余部分产生影响,但其影响不仅在事件手启动时发生。

什么解决办法符合反应模式? 我如何调整我的法典,以解决这个问题?

问题回答

我建议使用效果(避免造成问题)


    //Code

    const latestBRef = useRef(b);

    useEffect(() => {
      latestBRef.current = b;
    }, [b]);

    // inside your eventHandler , use latestBRef.current instead of b

Remove b as a dependecy from useCallback. If this is not helping , please put that in a code sandbox, so we can try different solutions.

在很多集思广益、撰写法典和打字之后(在大查小组的帮助下),我最后提出了一些似乎解决我问题的法典。 它可能不是精心设计的、简单、高效的、符合最佳做法的,但似乎在我使用的情况下是正确的。

I would be glad to get feedback on this solution, and if you know of a more efficient, React-friendly way of handling this problem, I would love to know about it!

Below is a revised version of my code that aims to provide a solution to the simplified problem (using a, b, and c) that I originally posted.

const useCustomHookArgs = [ foo ,  bar ]

// useCustomHook needs to be adapted to take a flag based on which it may or may not reset its state.
// I reset its state when using it in conjunction with useEventDependentEffect, but otherwise
// pass shouldResetState = false in the rest of my code

const useCustomHook = (shouldResetState = false, ...useCustomHookArgs) => {
  const [b, setB] = useState(null);
  const [shouldReset, setShouldReset] = useState(false);

  // Use an effect to set b and an internal shouldReset flag based on the shouldResetState arg
  useEffect(() => {
    const fetchData = async () => {
      // Logic to fetch data based on args
      const fetchedData = /* fetch logic */;

      setB(fetchedData);

      if (shouldResetState) {
        setShouldReset(true); // Flag needed to reset b after it has been used
      }
    };

    unsubscribeFromStore = subscribeToStore();
    fetchData();

    return () => {
      unsubscribeFromStore();
    };
  }, [...useCustomHookArgs]);

  // Use an effect to reset b (and the shouldReset flag) after it has been used
  useEffect(() => {
    if (shouldReset) {
      setB(null);
      setShouldReset(false);
    }
  }, [shouldReset]);

  return b;
};


// useEventDependentEffect is a custom hook that captures the logic needed to
// capture a at the time of the eventHandler call, and then compute b from a

const useEventDependentEffect = (eventHandler, effectFunction, aToCapture, computeB, computeBArgs) => {
  const [trigger, setTrigger] = useState(0);
  const capturedARef = useRef();
  const [capturedA, setCapturedA] = useState(null);
  const [computedB, setComputedB] = useState(null);


  const shouldResetState = true;

  const newComputedB = computeB(shouldResetState, ...computeBArgs, capturedA);


  useEffect(() => {
    if (newComputedB != null && newComputedB !== computedB) {
      setComputedB(newComputedB);
    }
  }, [newComputedB, computedB]);

  // Enhanced event handler to capture a and trigger the effect
  const enhancedEventHandler = useCallback((...args) => {
    eventHandler(...args);
    capturedARef.current = aToCapture.current;
    setTrigger(trigger + 1);  // Trigger the effect
  }, [eventHandler, trigger]);

  // Effect that runs the desired logic with the captured a
  useEffect(() => {
    if (trigger) {
      const newCapturedA = capturedARef.current;

      // Compare newCapturedA with the current capturedA
      if (newCapturedA !== capturedA) {
        setCapturedA(newCapturedA);
      }

      if(computedB != null) {
        // Call effectFunction with the computed b to run the logic
        // that needed to run below setA(c) in the original problem
        effectFunction(computedB, capturedARef.current);

        setTrigger(0);  // Reset the trigger
        setComputedB(null);
        setCapturedA(null);
      }
    }
  }, [trigger, effectFunction, capturedA, computeB, computedB]);

  return enhancedEventHandler;
};

function MyComponent(props) {
  const [a, setA] = useState(null);
  const aRef = useRef(a);

  const eventHandler = (event) => {
    const c = event.data;

    setA(c);
    aRef.current = c;
  };

  const effectFunction = async (b, a) => {
    try {
      if (b) {
        // logic using a
      } else {
        // more logic using a
      }
    } catch (e) {
      console.error(`Error:`, e);
    }
  };

  const aToCapture = {
    a: aRef
  }

  const handleEvent = useEventDependentEffect(eventHandler, effectFunction, aToCapture, useCustomHook, useCustomHookArgs);

  // Render logic and event binding using handleEvent
}




相关问题
selected text in iframe

How to get a selected text inside a iframe. I my page i m having a iframe which is editable true. So how can i get the selected text in that iframe.

How to fire event handlers on the link using javascript

I would like to click a link in my page using javascript. I would like to Fire event handlers on the link without navigating. How can this be done? This has to work both in firefox and Internet ...

How to Add script codes before the </body> tag ASP.NET

Heres the problem, In Masterpage, the google analytics code were pasted before the end of body tag. In ASPX page, I need to generate a script (google addItem tracker) using codebehind ClientScript ...

Clipboard access using Javascript - sans Flash?

Is there a reliable way to access the client machine s clipboard using Javascript? I continue to run into permissions issues when attempting to do this. How does Google Docs do this? Do they use ...

javascript debugging question

I have a large javascript which I didn t write but I need to use it and I m slowely going trough it trying to figure out what does it do and how, I m using alert to print out what it does but now I ...

Parsing date like twitter

I ve made a little forum and I want parse the date on newest posts like twitter, you know "posted 40 minutes ago ","posted 1 hour ago"... What s the best way ? Thanx.

热门标签