当前位置: 首页 > 知识库问答 >
问题:

仅在使用钩子单击按钮时更新react组件

闻人花蜂
2023-03-14

应用:

  1. 带有两个文本输入字段(input1、input2)的搜索栏
  2. 三个按钮:SearchX、SearchY、Clear Results
  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秒后,您将看到类似“Search X result with input:input1,input2”
  5. 更改任何输入框。无需按Enter。
  6. 3秒后,不单击按钮就会更改结果

可能的选项:

计划在更新结果组件之前使用react.memo钩子比较action prop。动作道具只能改变按钮点击,因此可以解决问题。

问题:

  1. 是否有其他方法(任何其他挂钩等)来解决此问题?
  2. 或者是否有任何其他流程/设计我可以遵循以避免备忘录?

共有2个答案

岳泉
2023-03-14

您可以使用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>
  );
}
吕子真
2023-03-14

您可以在输入交互时,将操作重置回NULL。这将清除当前结果,不会触发“搜索”。

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

  const onInput1Change = evt => {
    setInput1(evt.target.value);
    setAction(null);
  };
  const onInput2Change = evt => {
    setInput2(evt.target.value)
    setAction(null);
  };

  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(null)}>
        Clear results
      </button>
      <ResultComponent input1={input1} input2={input2} action={action} />
    </div>
  );
}

编辑使用html5表单保存输入并在提交时设置操作。当输入与交互时,状态中的输入直到表单提交后才更新。

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

  return (
    <div>
      <form
        id="searchX"
        onSubmit={e => {
          e.preventDefault();
          setInput1(e.target.inputX.value);
          setAction("SearchX");
        }}
      />
      <form
        id="searchY"
        onSubmit={e => {
          e.preventDefault();
          setInput2(e.target.inputY.value);
          setAction("SearchY");
        }}
      />

      <input id="inputX" form="searchX" type="text" />
      <input id="inputY" form="searchY" type="text" />

      <input form="searchX" type="submit" value="SearchX" />
      <input form="searchY" type="submit" value="SearchY" />
      <button type="button" onClick={() => setAction(null)}>
        Clear results
      </button>

      <ResultComponent input1={input1} input2={input2} action={action} />
    </div>
  );
}

此外,将“清除结果”按钮操作设置回null将保存ResultComponent中的条件检查,这将简化为:

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

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

  return null;
}
 类似资料:
  • 我正在React中使用useState钩子,状态将不会在

  • 使用React钩子,我想改变我的按钮的文本,当用户点击它说“添加”,然后我想设置回原来的文本“添加到购物车”后1秒。我假设我会为此使用setTimeout,但在这种情况下,我很难弄清楚如何使用它。 我有这个 到目前为止。

  • 我的代码生成一个输入字段,允许用户输入要搜索的值。然后当他们单击提交按钮时,它会使displayMap为true,因此当MapDisplay组件呈现时,它将通过Map组件触发API搜索并返回随后显示在地图上的值。 问题是这个过程只工作一次。当我再次单击该按钮时,它确实做了一些事情,我确认它正在输入框中获取新值,但我似乎不知道如何再次渲染地图。 我尝试在this.setState中设置其他变量,试图

  • 我有一个简单的部分,用户可以点击一个按钮,现在我想要点击改变(切换)文本的颜色,使用反应钩,这是我目前所拥有的。 因此,单击时初始颜色为黑色,我正在将颜色更改为。现在,再次单击时,颜色不会改变。 我需要添加什么,使这个切换在这两种颜色之间单击?

  • 问题内容: 我是Swing的新手。 我要在单击按钮(完成按钮)后更新表格。我认为数据正确,但屏幕无法正常工作。 以下是我程序的说明 选中复选框,然后单击完成按钮 最底层应更改。 没有主 这是我的代码: 问题答案: 而不是这样做… 只需更新现有模型 或简单地 假设您要继续向表中添加新行。如果您要这样做,还可以先清除表,然后再向其中添加新行。 Swing的工作原理是MVC(模型-视图- 控制器 ),该

  • 问题内容: 我正在使用此处找到的自定义表格模型。我已经使用该帖子中提供的建议更新了我的代码,并遇到了一个新问题。我对我的代码所做的改变是一个注入到我,以避免与线程的问题。完成此操作后,通过按按钮更新我的表的代码已停止工作。 用于初始化的代码如下: 我用来更新的代码如下: 我也尝试过使用,但这也不起作用。截至目前,更新的唯一方法是关闭并重新打开程序。具有我正在使用的,随着用户添加更多玩家,尺寸会增加