反应挂钩中的最大更新深度超出错误

时间:2020-05-11 08:34:41

标签: reactjs formik

我正在尝试根据从下拉列表中选择的值和从后端获取的值来更新状态,但是它陷入了循环并达到了最大深度。

export function something(){
const [getState, setState] = useMergeState({
    isValue: false,
    initialState: {
      a: '',
      b: '',
      c: '',
      d: ''
    }
})

const fetchData = () => {
   apiCall().then(res => {
   if(res.status === 200){
     setState({
       initialState: {
         ...initialState,
         d:response.data
       }  
     })
   }
})
}

useEffect(() => {
 if(getState.isValue) fetchData()
})

const renderView = (props) => {
let {values} = props;
values.something === 'xyz' && setState({isValue: true})
return(
   <Dropdown>
   <Dropdown>
)}

return(
   <Formik initialValue={getState.initialState} render={renderView}/>
)}

在此代码中,我尝试根据所选的输入设置setState,如果输入selected === 'xyz',则setState为true,如果isValue的值为true,则它将命中api以获取一些数据并将其存储在州。问题是,一旦我尝试在 renderView 中设置状态,它就会陷入无限循环。我无法在其他任何地方选择选定的值。

谢谢

2 个答案:

答案 0 :(得分:0)

const fetchData = () => {
   apiCall().then(res => {
   if(res.status === 200){
     setState({
      isValue: false, // Changes here
       initialState: {
         ...initialState,
         d:response.data
       }  
     })
   }
})
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

通过在此处更改一些逻辑来更新答案,我看不到isValue状态的任何用途,因此我将其删除。如果您认为自己仍然需要isValue,请对其进行描述。

export function something(){
  const [initialState, setInitialState] = useState({
    a: '',
    b: '',
    c: '',
    d: ''
  })
  
  const fetchData = () -> {
    apiCall().then(res => {
      if (res.status === 200) {
        setInitialState({ ...initialState, d: response.data })
      }
    })
  }
  
  const renderView = props => {
  
    // If you are going to fetch on the first time,
    useEffect(fetchData, [])
    
    // If you are looking to fetch everytimes the values update
    useEffect(fetchData, [props.values])
    
    return (
      <Dropdown>
    )
  }

return(
   <Formik initialValue={getState.initialState} render={renderView}/>
)}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

答案 1 :(得分:0)

清洁代码-分开的东西

我建议这样做(代码):

它更清晰易懂。

export function something() {
  const initState = { a: '', b: '', c: '', d: '' };

  const [state, setState] = useState(initState);
  const [isValue, setIsValue] = useState(false);

  const fetchData = async () => {
    const res = await apiCall();
    if (res.status === 200) setState({ ...state, d: res.data });
  }

  useEffect(() => {
    if (isValue) fetchData();
  })

  const renderView = ({ values }) => {
    if (values.something === 'xyz') setIsValue(true);
    return <Dropdown></Dropdown>
  }

  return (
    <Formik initialValue={initState} render={renderView} />
  )
}

它可以更加清晰,就像initState的键不是a,b,c,d一样。并命名更有意义。

对于您的问题,由于您不能return <Dropdown></Dropdown>,因为它是Formik可以激活但不响应的功能,因此应删除此语句。并且您应该将isValue传递给Formik组件,并通过isValue值有条件地在Dropdrop内部进行渲染。