首页 > 解决方案 > 避免警告的方法:React 检测到 Hooks 的顺序发生了变化

问题描述

我有一个组件,当应用程序中其他地方的状态发生变化时,它会调度一些操作。但这以某种方式给了我可怕的change in the order of Hooks错误。

在阅读钩子规则时,它说基本上在条件句中包装钩子是禁止的......我目前没有这样做。

但是,随着服务器加载数据,我正在呈现项目列表并且这些列表的值发生变化。使用选择器和 redux-sagas 使得所有这些都无法实际调试,那么我还能如何追踪问题的根源呢?

我有一个组件:

const PhraseList = props => {
    const trainingPhrases = useSelector(selectFilteredPhrases());

    return (
        <div className={styles.Wrapper}>
            <ul className={opStyles.listReset}>
                {  
                    trainingPhrases.map((phrase, idx) => {
                        return PhraseItem({ phrase, idx });
                    })
                }
            </ul>
        </div>
    );

它调用PhraseItem组件,该组件引发错误。

const PhraseItem = ({ phrase, idx }) => {
    // this line chokes
    const [checked, setChecked] = useState(false);

    return (
        <li key={"tr-" + idx}>
            <div className={styles.container}>
                <div className={styles.phraseText}>{phrase.text}</div>
            </div>
        </li>
    );
};

我正在调试选择器(选择器工厂)中的更改,这似乎是触发应用程序崩溃的原因。

export const selectFilteredPhrases = () =>
    createSelector(trainingPhrases, phraseFilter, (trainingPhrases, phraseFilter) => {
        console.log('trainingPhrases', trainingPhrases)
        return trainingPhrases
    });

但是如果数据没有改变,那么很难构建一个应用程序:O

我看到了一个我认为不相关的关于使用 JSX 的答案。在这个问题上没有太多其他内容。

redux, sagas, hooks, selectors...react DSL 层数越来越多,很难在框架中深入调试。

更新。我认为这可能是因为我一个接一个地调用两个 saga,这会导致 UI 中出现某种竞争条件?

    const pickIntent = () => {
        dispatch(pickIntentAction(intentId));
        dispatch(getIntentPhrasesAction(intentId));

调试日志

标签: reactjsreduxredux-saga

解决方案


我认为这个答案是相关的,因为它已经在这个链接中提到,如果你调用 jsx 组件作为一个函数 react 认为,在这个 jsx 函数中声明的钩子是应用程序组件的一部分,所以如果你的数组trainingPhrases有更少第一次渲染的元素比第二次渲染的元素会导致这个警告(渲染的 jsx 组件会更少,这意味着钩子会更少)。解决方案很简单,像这样调用 jsx 组件<PhraseItem phrase={phrase} idx={idx} />


推荐阅读