简体   繁体   English

在 React JS 中使用 onchange function 的 useCallback

[英]useCallback with onchange function in React JS

I have 2 components.我有 2 个组件。 In the parent component I have this:在父组件中我有这个:

const Demo = () => {
  const [state, setState] = useState(true);
  const onChange = useCallback(
    (value: string) => {
      console.log(value);
    },
    [],
  );

  return (
    <div className="a">
      <button onClick={() => setState(!state)}>sds</button>
      <div className="123">
        <Bar searchHandler={onChangeSearchHandler} />
      </div>
    </div>
  );
};

In the Bar component I have this:Bar组件中,我有这个:

const Bar = ({ searchHandler }) => {
    console.log('bar');
  return (
    <div>
      <input type="text" onChange={(value) => searchHandler(value.target.value)} />
    </div>
  );
};

Wrapping onChange with useCallback I expect to cache the function and when I click on <button onClick={() => setState(false)}>sds</button> I don't want to render Bar component, but it is triggered.useCallback包装onChange我希望缓存 function,当我点击<button onClick={() => setState(false)}>sds</button>我不想渲染Bar组件,但它被触发了。 Why Bar component is triggered and how to prevent this with useCallback ?为什么触发Bar组件以及如何使用useCallback来防止这种情况发生?

This has nothing to do with the onChange function you're wrapping with useCallback .这与您使用useCallback包装的onChange函数useCallback Bar gets re-rendered because you're changing the state through setState in its parent component. Bar被重新渲染,因为您正在通过其父组件中的setState更改状态。 When you change the state in a component all its child components get re-rendered.当您更改组件中的状态时,它的所有子组件都会重新渲染。

You can verify it yourself by trying this:您可以通过以下方式自行验证:

const Demo = () => {
  const [state, setState] = useState(true);

  return (
    <div className="a">
      <button onClick={() => setState(!state)}>sds</button>
      <div className="123">
        <Bar />
      </div>
    </div>
  );
};
const Bar = ({ searchHandler }) => {
  console.log('bar');

  return (
    <div></div>
  );
};

You'll see that the Bar gets re-rerender anyway.你会看到Bar无论如何都会重新渲染。

If you want to skip re-rerendring any of the child components, you should memoize them using React.memo when applicable.如果你想跳过重新渲染任何子组件,你应该在适用时使用React.memo 记住它们。

Also, you should familiarize yourself with how state in react works and how does it affect the nested components as this is a main concept .此外,您应该熟悉 React 中的状态如何工作以及它如何影响嵌套组件,因为这是一个主要概念

The issue is that you haven't used React.memo on Bar component.问题是您没有在 Bar 组件上使用React.memo The function useCallback works only if you use HOC from memo.仅当您使用备忘录中的 HOC 时,function useCallback才有效。

try this, in Bar component create this wrapped component:试试这个,在 Bar 组件中创建这个包装组件:

const WrappedBar = React.memo(Bar);

and in parent component use this wrapped bar:并在父组件中使用这个包装栏:

const Demo = () => {
  const [state, setState] = useState(true);
  const onChange = useCallback(
    (value: string) => {
      console.log(value);
    },
    [],
  );

  return (
    <div className="a">
      <button onClick={() => setState(!state)}>sds</button>
      <div className="123">
        <WrappedBar searchHandler={onChangeSearchHandler} />
      </div>
    </div>
  );
};

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

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