如何防止自定义输入重新渲染 onChange,同时通知父组件有关此更改的信息?

问题描述 投票:0回答:2

我的目的是创建一个自定义输入元素,避免在输入值更改时重新渲染,但同时如果输入更改则通知父级。

输入组件:

import { useRef, useEffect, ChangeEvent } from "react";

type props = {
changeFunction?: (e: ChangeEvent<HTMLInputElement>) => void;
};

function TestInput({ changeFunction }: props) {
let inputRef = useRef<HTMLInputElement>(null);

useEffect(() => {
  console.log("Input render");
});

function change(e: ChangeEvent<HTMLInputElement>) {
  console.log("Input change", e.target.value);
  if (inputRef.current) inputRef.current.value = e.target.value;
  if (changeFunction) changeFunction(e);
}

return (
  <input
    ref={inputRef}
    type="search"
    id="test"
    name="test"
    autoComplete="off"
    onChange={change}
  />
);
}

export default TestInput;

父组件:

import { useCallback, useState, ChangeEvent } from "react";
import TestInput from "./Test";

function TestParent() {
  let [value, setValue] = useState("");
  let change = useCallback(
    (e: ChangeEvent<HTMLInputElement>) => setValue(e.target.value),
    []
  );

  return (
    <div>
      <p>Value: {value}</p>
      <TestInput changeFunction={change} />
    </div>
  );
}

export default TestParent;

尽管使用了

useCallback
,输入组件每次都会重新渲染。如果我们排除
changeFunction
属性,这种情况就不会发生。有什么解决办法吗?

这是一个堆栈片段,没有显示问题的 TypeScript 部分。

const { useState, useEffect, useCallback, useRef } = React;

function TestInput({ changeFunction }) {
  let inputRef = useRef(null);

  useEffect(() => {
    console.log("Input render");
  });

  function change(e) {
    console.log("Input change", e.target.value);
    if (inputRef.current) inputRef.current.value = e.target.value;
    if (changeFunction) changeFunction(e);
  }

  return (
    <input
      ref={inputRef}
      type="search"
      id="test"
      name="test"
      autoComplete="off"
      onChange={change}
    />
  );
}

function TestParent() {
  let [value, setValue] = useState("");
  let change = useCallback(
    (e) => setValue(e.target.value),
    []
  );

  return (
    <div>
      <p>Value: {value}</p>
      <TestInput changeFunction={change} />
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<TestParent />);
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

javascript reactjs
2个回答
1
投票

您可以使用

React.memo
。因为输入属性没有改变,所以当其父状态改变时,输入不会被重新渲染。

export default React.memo(TextInput);

0
投票

您不需要避免子组件的重新渲染。这就是 React 计算出对 dom 进行必要更改的方式。因此,除非您的用例特别要求子组件不重新渲染,否则您应该避免此类性能优化。

您可以记忆子组件

import { memo } from 'react';

// ...

export default memo(TestInput);
© www.soinside.com 2019 - 2024. All rights reserved.