Home > Enterprise >  Set value and trigger action when dropdown value is changed
Set value and trigger action when dropdown value is changed

Time:01-10

I have this React select dropdown:

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>

I need to set the selected value to exchangeId and call handleSyncList. Is it possible first to set the option value and then call handleSyncList using useEffect like this:

useEffect(callback, [dep])

CodePudding user response:

You can set handleSyncList as useEffect callback and define exchangeId as one of useEffect dependencies, and whenver exchangeId updates, your handleSyncList will call with the update value of exchangeId, like this;

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>

Consider that, in this manner handleSync will call in the first render, you can controll it by checking that exchangeId has value or not, or you can define a variable by react useRef and controll that is the first render of component or not, like this:

...
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 } , []);
...

CodePudding user response:

i cant' comment the post I propose to use the useState callback just after setting the state

<select onChange={e => setExchangeId(e.target.value, () => handleSyncList()}>

CodePudding user response:

useEffect(() => {
if(exchangeId !== "") handleSyncList()
},[exchangeId])

it will guarantee the order you want.

CodePudding user response:

Yes, but you have to make sure you only run it, when exchangeId is changed, so you have to store previous exchangeId value somewhere, ideally in ref.

const [exchangeId, setExchangeId] = useState('');
const lastExchangeId = useRef(exchangeId);

//...

useEffect(() => {
  if (exchangeId !== lastExchangeId.current) {
    handleSyncList();
    lastExchangeId.current = exchangeId;
  }
}, [exchangeId])
  •  Tags:  
  • Related