仅在单击带有钩子的按钮时更新React组件

时间:2020-03-04 04:04:01

标签: reactjs react-hooks

应用

  1. 带有两个文本输入字段(input1,input2)的搜索栏
  2. 三个按钮:SearchX,SearchY,清除结果
  3. 这两个搜索都可以将input1和input2作为参数来给出两个不同的结果。
  4. 有一个结果组件,它既可以接受输入也可以进行操作,并根据操作来呈现搜索组件。
function TestComponent() {
  const [input1, setInput1] = useState('');
  const [input2, setInput2] = useState('');
  const [action, setAction] = useState(null);

  const onInput1Change = evt => setInput1(evt.target.value);
  const onInput2Change = evt => setInput2(evt.target.value);

  return (
    <div>
      <input type="text" value={input1} onChange={onInput1Change} />
      <input type="text" value={input2} onChange={onInput2Change} />
      <button type="button" onClick={() => setAction('SearchX')}>
        SearchX
      </button>
      <button type="button" onClick={() => setAction('SearchY')}>
        SearchY
      </button>
      <button type="button" onClick={() => setAction('Clear results')}>
        Clear results
      </button>
      <ResultComponent input1={input1} input2={input2} action={action} />
    </div>
  );
}

function ResultComponent({ input1, input2, action }) {
  if (action === 'SearchX') {
    return <SearchX input1={input1} input2={input2} />;
  }

  if (action === 'SearchY') {
    return <SearchY input1={input1} input2={input2} />;
  }

  if (action === 'Clear results') {
    return null;
  }

  return null;
}

function SearchX({ input1, input2 }) {
  const [result, setResult] = useState(null);

  useEffect(() => {
    // Fetch and process X-way to get the result. Using timeout to simulate that
    const id = window.setTimeout(() => setResult(`Search X result with inputs: ${input1}, ${input2}`), 3000);
    return () => window.clearInterval(id);
  }, [input1, input2]);

  return <div>{result}</div>;
}

function SearchY({ input1, input2 }) {
  const [result, setResult] = useState(null);

  useEffect(() => {
    // Fetch and process Y-way to get the result. Using timeout to simulate that
    const id = window.setTimeout(() => setResult(`Search Y result with inputs: ${input1}, ${input2}`), 3000);
    return () => window.clearInterval(id);
  }, [input1, input2]);

  return <div>{result}</div>;
}

ReactDOM.render(<TestComponent />, document.getElementById('root'));

问题

我们希望搜索仅在单击按钮时才开始。使用下面的代码,在第一个搜索结果之后,一旦您更改输入,结果组件就会重新呈现,从而无需单击按钮即可再次启动搜索

重现该问题的步骤:

  1. 在第一个文本框中输入“ input1”
  2. 在第二个文本框中输入“ input2”
  3. 点击“ SearchX”
  4. 3秒钟后,您应该看到类似“使用输入搜索X结果:input1,input2”
  5. 更改任何输入框。无需按Enter。
  6. 3秒后,结果将发生变化,而无需单击按钮

可能的选项

计划在更新结果组件之前使用React.memo钩子比较动作道具。动作道具只能通过单击按钮来更改,因此可以解决问题。

问题

  1. 还有其他方法(其他钩子等)来解决问题吗?
  2. 或者还有其他可避免备忘录的流程/设计吗?

1 个答案:

答案 0 :(得分:0)

您可以使用refs进行输入,并且仅在单击按钮时更新状态。

export default function TestComponent() {
  const [input1, setInput1] = useState("");
  const [input2, setInput2] = useState("");
  const [action, setAction] = useState(null);

  const input1Ref = useRef(null);
  const input2Ref = useRef(null);

  const onButtonClick = () => {
    if (input1Ref.current) {
      setInput1(input1Ref.current.value);
    }
    if (input2Ref.current) {
      setInput2(input2Ref.current.value);
    }
  };

  const onSearchXClick = () => {
    onButtonClick();
    setAction("SearchX");
  };

  const onSearchYClick = () => {
    onButtonClick();
    setAction("SearchX");
  };

  return (
    <div>
      <input ref={input1Ref} type="text" />
      <input ref={input2Ref} type="text" />
      <button type="button" onClick={onSearchXClick}>
        SearchX
      </button>
      <button type="button" onClick={onSearchYClick}>
        SearchY
      </button>
      <button type="button" onClick={() => setAction("Clear results")}>
        Clear results
      </button>
      <ResultComponent input1={input1} input2={input2} action={action} />
    </div>
  );
}

Edit silly-maxwell-usrrj