【问题标题】:Change in the order of Hooks called by <Component><Component> 调用 Hooks 的顺序变化
【发布时间】:2020-01-15 11:26:17
【问题描述】:

我收到关于 React has detected a change in the order of Hooks called by Checkout 的警告

我确实阅读了https://reactjs.org/docs/hooks-rules.html 并且看起来我的代码符合要求

警告: screenshot from debbuger

带有钩子的文件片段:

  if (!token) {
    navigate.push(routes.login)
    return <Text>Redirect</Text>
  }

  const maximumDate = moment().add(1, 'year')
  const minimumDate = moment()
  const formattedToday = minimumDate.format('YYYY-MM-DD')

  const [paymentMethod, setPaymentMethod] = useState(paymentOptions[0].key)
  const [totalAmount, setTotalAmount] = useState(totalCartAmount)
  const [deliveryTime, setDeliveryTime] = useState(0)
  const [date, setDate] = useState(minimumDate)
  const [show, setShow] = useState(false)

  const validationSchema = yup.object().shape({
    couponCode: yup.string(),
    comments: yup.string(),
  })

  useEffect(() => {
    if (deliverySlots.length > 0) {
      setDeliveryTime(deliverySlots[0].id)
    }
  }, [deliverySlots])

  useEffect(() => {
    getDeliveryTimeSlots(country.id, formattedToday, error => {
      if (error) {
        console.log(error)
      }
    })
  }, [])

完整的组件代码: https://codesandbox.io/s/modest-lewin-4x9ss

【问题讨论】:

  • 你在一个条件之后执行钩子(即if (!token)

标签: javascript reactjs react-native react-hooks


【解决方案1】:

如果您的组件中有钩子,则必须确保在每次渲染时以相同的顺序调用所有钩子。这段代码应该放在所有钩子之后(因为return):

if (!token) {
  navigate.push(routes.login)
  return <Text>Redirect</Text>
}

【讨论】:

    【解决方案2】:

    我在 React Native 上遇到了同样的错误...

    仔细观察错误信息后,我意识到: 我正在从父屏幕所依赖的子屏幕中删除处于 redux 状态的数据。

    例如:ProfileScreen => SettingScreen

    在上面的例子中,SettingScreenProfileScreen 的子屏幕。 因此,当您从 SettingScreen 中删除 ProfileScreen 所引用的 redux 状态中的数据时,您将收到相同的错误,因为 ProfileScreen useContext 未从 redux 中定义。

    我是如何解决的:

    来自:

    const someTask = () => {
       ....
       dispatch(deleteData(dataId))
       navigation.navigate('HomeScreen')
    }
    

    收件人:

    const someTask = () => {
       ....
       navigation.navigate('HomeScreen')
       dispatch(deleteData(dataId)) //deleting the Data should be the last thing to do to safely navigate away..
    }
    

    【讨论】:

    • 这是我的问题的解决方案。
    • @MathisHard 很高兴它确实解决了您的问题! :))
    【解决方案3】:

    既然已经列出了hook的规则,那你肯定漏掉了`Only Call Hooks at the Top Level"的重要部分

    它说:

    不要在循环、条件或嵌套函数中调用 Hooks。相反,请始终在 React 函数的顶层使用 Hooks

    简单地说,要么将你的钩子移到条件之上,要么将条件提取到父函数/组件。

    【讨论】:

      【解决方案4】:

      在我的情况下,我的组件顶部有一条简单的线,例如:

      if (isLoading) return <dev>Loading..</dev>
      

      在声明常量和变量之后,我将这一行移到通常应该返回的末尾后,错误消失了..

      【讨论】:

        猜你喜欢
        • 2019-12-15
        • 2021-11-05
        • 1970-01-01
        • 2021-10-02
        • 2022-10-02
        • 2021-12-15
        • 2019-12-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多