【问题标题】:Set value and trigger action when dropdown value is changed更改下拉值时设置值和触发动作
【发布时间】:2022-01-10 09:14:58
【问题描述】:

我有这个 React 选择下拉菜单:

const handleSyncList = () => {
    ......
};
const [exchangeId, setExchangeId] = useState('');

<select onSelect={e => setExchangeId(e.target.value)} onChange={handleSyncList}>
  <option value="">All Exchanges</option>
  {exchangesList.map(otherEntity => (
        <option value={otherEntity.exchangeId}>
          .......
        </option>
      ))
    : null}
</select>

我需要将选定的值设置为exchangeId 并调用handleSyncList。 是否可以先设置选项值,然后使用 useEffect 调用handleSyncList,如下所示:

useEffect(callback, [dep])

【问题讨论】:

  • 你可以按顺序调用它:onSelect={e =&gt; { setExchangeId(e.target.value); handleSyncList(); } }
  • 我测试了您的提议,但看起来首先调用了handleSyncList,然后调用了etExchangeId。结果是下次我更改下拉值时,会显示正确的搜索值。知道如何防止这种情况发生吗?

标签: javascript reactjs typescript


【解决方案1】:

您可以将handleSyncList 设置为useEffect 回调并将exchangeId 定义为useEffect 依赖项之一,并且每当exchangeId 更新时,您的handleSyncList 将使用exchangeId 的更新值调用,例如这个;

const exchangesList = ['a','b','c']
const App = ()=> {
  const [exchangeId, setExchangeId] = React.useState('');
   const handleSyncList = () => {
        console.log(exchangeId); // or whatever else
   };
  React.useEffect(handleSyncList , [exchangeId]);

   return (
     <select onChange={e => setExchangeId(e.target.value)}>
      <option value="">All Exchanges</option>
      {exchangesList.map(otherEntity => (
            <option value={otherEntity}>
              {otherEntity}
            </option>
          ))
       }
    </select>
   )
}

ReactDOM.render(<App/>, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>

考虑一下,handleSync 会以这种方式调用第一个渲染,您可以通过检查 exchangeId 是否具有值来控制它,或者您可以通过反应 useRef 和 controll 定义一个变量组件的第一次渲染与否,像这样:

...
const [exchangeId, setExchangeId] = React.useState('');
const isMounted = React.useRef(false);
const handleSyncList = () => {
  if(isMounted.current){
   console.log(exchangeId); // or whatever else
  }
};
React.useEffect(handleSyncList , [exchangeId]);
React.useEffect(()=> { isMounted.current = true } , []);
...

【讨论】:

    【解决方案2】:

    是的,但是您必须确保仅在 exchangeId 更改时才运行它,因此您必须将以前的 exchangeId 值存储在某个地方,最好是在参考文献中。

    const [exchangeId, setExchangeId] = useState('');
    const lastExchangeId = useRef(exchangeId);
    
    //...
    
    useEffect(() => {
      if (exchangeId !== lastExchangeId.current) {
        handleSyncList();
        lastExchangeId.current = exchangeId;
      }
    }, [exchangeId])
    

    【讨论】:

      【解决方案3】:

      我不能评论帖子 我建议在设置状态后使用 useState 回调

      【讨论】:

        【解决方案4】:
        useEffect(() => {
        if(exchangeId !== "") handleSyncList()
        },[exchangeId])
        

        它将保证您想要的顺序。

        【讨论】:

        • 我还需要更新下拉代码吗?
        • 这也会在组件挂载时自动运行handleSyncList
        • @user1285928
        • @BorisTB 我编辑了代码以避免在首次安装组件时运行 handleSyncList()
        猜你喜欢
        • 2011-09-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-26
        • 2018-12-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多