简体   繁体   English

当多个状态导致多次重新渲染时,直接在React函数组件中执行代码

[英]Code Execution Directly in a React Function Component, When Multiple States Causes Multiple Re-Renders

I have component that uses both useState() and other custom hooks multiple times. 我有多次使用useState()和其他自定义钩子的组件。

I want to act based on these state values. 我想根据这些状态值采取行动。 I could do that directly in the function component's body: 我可以直接在功能组件的主体中执行此操作:

const MyComponent = () => {
  const [someState, setSomeState] = useState(false);
  const [otherState, setOtherState] = useState(false);
  const customHookValue = useCustomHook();

  if (someState) foo();
  const foo = () => setOtherState(!otherState);

  if (customHookValue > 10) bar();
  const bar = () => setSomeState(somestate > customHookValue);
}

However, every time someState changes (and a re-render happens) the second conditional also runs, causing bar() to run if the conditional passes. 但是,每次someState更改(并且发生重新渲染)时,第二个条件也会运行,如果条件通过, bar()就会运行。 This feels unnatural. 感觉不自然。 Logically, bar() should only run when customHookValue changes, as someState only changes if customHookValue has changed since last render. 从逻辑上讲, bar()仅应在customHookValue更改时运行,因为someState仅在customHookValue自上次渲染以来已更改时才更改。

In summary, a re-render caused by a change to someState should not cause a bunch of unrelated state setting functions to run again. 总之,由对someState的更改引起的重新渲染不应导致大量不相关的状态设置函数再次运行。 Even though re-running them causes no change in the outcome of the program, it is not logically right. 即使重新运行它们不会导致程序结果发生变化,但从逻辑上讲这也不对。 They only need to re-run when their corresponding conditional changes. 他们只需要在其相应的条件更改时重新运行即可。 It could effect performance. 它可能会影响性能。

This must be a common challenge in React. 这一定是React中的常见挑战。 I am quite new to it, so I do not know what the approach to solve this would be. 我对此很陌生,所以我不知道解决该问题的方法是什么。

Questions 问题

  1. How would I solve the above in the recommended manner? 我将如何以建议的方式解决上述问题?
  2. Would I have to wrap every conditional in a useEffect or a useMemo ? 我是否必须将每个条件包装在useEffectuseMemo

EDIT: 编辑:

Updated the second conditional, to make my question clearer (it should depend on customHook). 更新了第二个条件,以使我的问题更清楚(它应取决于customHook)。


CLARIFICATION: 澄清:

As it might not have been clear, my issue is as follows. 可能不清楚,我的问题如下。 When state changes, a re-render occurs. 状态更改时,将进行重新渲染。 This causes all functions in the component's body to re-run. 这将导致组件主体中的所有功能重新运行。 Now, if we have many useState in a component, and only one changes, a bunch of potentially unrelated state-changing and potentially expensive functions I have defined in the components body will run. 现在,如果我们在一个组件中有许多useState ,并且只有一个更改,那么我在组件主体中定义的一堆可能不相关的状态改变和潜在昂贵的函数将运行。 These state-changing functions would only have to run if the state values they are trying to set has changed. 这些状态更改功能仅在它们尝试设置的状态值已更改时才必须运行。 If the values they are setting has not changed, it is unnecessary for them to run again. 如果它们设置的值未更改,则无需再次运行。 But, the re-render reruns all functions in the component's body regardless. 但是,无论如何,重新渲染都会重新运行组件主体中的所有功能。

It looks like (as others have suggested) you want useEffect : 看起来(正如其他人所建议的那样),您需要useEffect

useEffect(() => {
  if (someState) {
    setOtherState(!otherState)
  }
}, [someState, otherState])
useEffect(() => {
  if (customHookValue > 10) {
    setSomeState(someState > customHookValue)
  }
}, [customHookValue])

Since you only want the setSomeState to run if customHookValue changes, make it the only item in the dependencies array passed to useEffect . 既然你只希望setSomeState运行,如果customHookValue变化,使它的依赖性阵列传递到的唯一项目useEffect

The exhaustive-deps eslint-plugin-react-hooks will complain about the second useEffect, since the function depends on the value of someState , even though someState will only potentially change if customHookValue changes. exhaustive-deps eslint-plugin-react-hooks将抱怨第二个useEffect,因为该函数取决于someState的值,即使someState仅在customHookValue更改时才可能更改。 I also wouldn't worry about things potentially affecting performance until they do. 我也不会担心可能影响性能的事情,除非它们确实会影响性能。 I don't know a ton about the internals of React, but it does some things under the hood to avoid re-renders it doesn't need to do, and can do multiple renders before an actual update is painted. 我对React的内部知识一无所知,但是它在幕后做了一些事情来避免重新渲染它不需要做的事情,并且可以在绘制实际更新之前进行多次渲染。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM