开发者问题收集

React useeffect 导致无限循环

2022-09-25
84

我是 React 的新手,正在创建一个自定义选择组件,该组件应该设置一个数组选定状态,同时触发 onchange 事件并将其与选定项一起传递给父级,同时获取初始值作为 prop 并设置一些数据。

let firstTime = true;
const CustomSelect = (props)=>{
    
    const [selected, setSelected] = useState([]);

     const onSelectedHandler = (event)=>{
         
        // remove if already included in the selected items remove 
        //otherwise add

         setSelected((prev)=>{
            if (selected.includes(value)) {
                values =  prevState.filter(item => item !== event.target.value);
             }else {
                values =  [...prevState, event.target.value];
             }
            return values;
         })

         // tried calling props.onSelection(selected) but its not latest value
     }

   //watch when the value of selected is updated and pass onchange to parent 
   //with the newest value
   useEffect(()=>{
     if(!firstTime && props.onSelection){
          props.onSelection(selected);
      }
    firstTime = false;
   },[selected])
     
   
   return (<select onChange={onSelectedHandler}>
              <option value="1"></option>
            </select>);

 };

我正在像这样的父级上使用它

 const ParentComponent = ()=>{

   const onSelectionHandler = (val)=>{
      //do stuff with the value passed
    }

   return (
    
     <CustomSelect initialValue={[1,2]} onSelection={onSelectionHandler} />

  );

  }

 export default ParentComponent

上面的方法运行良好,但现在问题出现了,当我想通过更新选定状态将从父级传递的 initialValue 设置为 customSelect 时。我在 CustomSelect 上添加了以下内容,但它会导致无限循环

const {initialValue} = props
useEffect(()=>{
  //check if the value of initialValue is an array 
  //and other checks
   setSelected(initialValue) 
 
 },[initialValue]);

我知道我可以在 useState 中传递 initialValue,但我想在设置选定状态之前做一些检查。 我该如何解决这个问题,我还是 React 的新手。

2个回答

在您的 //使用传递的值进行操作 中,您很可能会更新组件父组件的状态,这会导致重新渲染父组件。传递 prop initialValue={[1,2] 时,会在每次渲染时创建一个新的 [1,2] 数组实例,并导致 useEffect 上的无限渲染。为了解决这个问题,您可以将 initialValue prop 移动到其他地方作为 const 值,如下所示:

const INITIAL_VALUE_PROP = [1,2];
const ParentComponent = ()=>{

   const onSelectionHandler = (val)=>{
      //do stuff with the value passed
    }

   return (

     <CustomSelect initialValue={INITIAL_VALUE_PROP} onSelection={onSelectionHandler} 
     />

  );

}

export default ParentComponent
Ahmet Emre Kilinc
2022-09-25

好的,发生这种情况的原因是您将 initialValue 属性作为数组传递,并且由于这是 JavaScript 中的引用值,这意味着每次传递(更新)时,都会传递不同的引用值/地址,因此效果将无限期地重新运行。解决此问题的一种方法是使用 React.useMemo 文档在这里 来存储/保留传递的数组的引用值,不会导致不必要的副作用运行。

Abdulrahman Ali
2022-09-25