【问题标题】:Maximum update depth exceeded error in react hooks反应钩子中的最大更新深度超出错误
【发布时间】:2020-08-26 17:51:04
【问题描述】:

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

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}/>
)}

在这段代码中,我试图根据选择的输入设置状态,如果输入selected === 'xyz',那么它将 setState 为真,如果 isValue 的值为真,那么它将点击 api 获取一些数据并将其存储在状态中。问题是一旦我尝试在 renderView 中设置状态,它就会陷入无限循环。我无法在其他任何地方获得选择的值。

谢谢

【问题讨论】:

  • 你将isValue设置为true,当你再次设置为false时?

标签: reactjs formik


【解决方案1】:

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>

【讨论】:

  • 它不起作用,因为它再次进入 renderView 并看到 values.something === 'xyz' 并将其设置为 isValue 再次为 true 并进入无限循环
【解决方案2】:

干净的代码 - 分开的东西

我的建议是这样做(代码):

更清晰易懂。

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 &lt;Dropdown&gt;&lt;/Dropdown&gt; 因为它是 Formik 可以激活但不响应它的功能,所以该语句应该删除。您应该将 isValue 传递给 Formik 组件,并通过 isValue 值有条件地在内部渲染 Dropdown。

【讨论】:

  • 感谢@Omer,您建议的重构可以做到这一点,但这对解决问题没有帮助
  • 对不起,我忘记了,你的问题是因为你不能return &lt;Dropdown&gt;&lt;/Dropdown&gt;,因为这是一个Formik可以激活但不响应的功能,这个语句应该删除。并且您应该将 isValue 传递给 Formik 组件,并通过 isValue 值有条件地在内部渲染 Dropdown。
猜你喜欢
  • 2021-10-01
  • 2020-08-29
  • 2019-10-09
  • 1970-01-01
  • 2021-05-15
  • 2021-06-20
  • 2020-09-23
  • 1970-01-01
  • 2021-10-13
相关资源
最近更新 更多