简体   繁体   中英

How to remove the renderer of a functional memoized component that contains a child component in React?

When writing a handler for several different inputs, I ran into the problem of re-rendering components in which there are child components. How can I remove the renderer?

Only components without children and components using useMemo are not rendered.

This is only part of the code. Here full code .

// handle changes from input
export const useInputHandler = ({ initValues }) => {
  const [values, setValues] = useState(initValues || {});

  const handlerChange = useCallback(
    event => {
      const target = event.target;
      const name = target.name;
      const value = target.value;

      setValues({
        ...values,
        [name]: value
      });
    },
    [values]
  );

  return [values, handlerChange];
};
const App = () => {
  const [clicksNum, setClicks] = useState(0);

  const countClicks = useCallback(() => {
    setClicks(c => c + 1);
  }, []);

  const [values, handleChange] = useInputHandler({
    initValues: { simple: "", counter: "", empty: "" }
  });

  useEffect(() => {
    console.log("VALUES: ", values);
  }, [values, clicksNum]);

  return (
    <div style={{ display: "flex", flexDirection: "column", width: "30%" }}>
      <Button onClick={countClicks} />

      <Input onChange={handleChange} name="simple" value={values.simple}>
        {<div>hello</div>}
      </Input>

      <Input onChange={handleChange} name="counter" value={values.counter}>
        {clicksNum}
      </Input>

      <Input onChange={handleChange} name="empty" value={values.empty} />
    </div>
  );
};

I expect that the input components will not be re-render every time the button is clicked. In this case, only the second input (which name counter ) should be redrawn. Because it wraps up the value ( clicksNum ) of the state.

Your input re-renders, because it's children change.

{<div>Hello</div>} is a different instance at every render.

If you replace this with something like this:

const hello = useMemo(() => <div>Hello</div>, []);

It will only create a new instance if any of the dependencies change. There are no dependencies, and your re-renders will be gone.

You can always prevent unwanted re-renders by memoizing any of your components, it will then re-render only if any of the dependencies change.

const memoizedInput = React.useMemo(
  () => (
    <Input onChange={handleChange} name="simple" value={values.simple}>
      <Button onClick={countClicks} />
    </Input>
  ),
  [handleChange, countClicks, values.simple]
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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