首页 > 解决方案 > React 检测到 Hooks 的顺序发生了变化

问题描述

我收到此错误,Warning: React has detected a change in the order of Hooks called by Thread.

但是我看不到问题,我在函数的顶部调用它,我想我用这段代码有条件地渲染它

if (loading) {
    return <Text>{loading ? 'Loading...' : null}</Text>;
}

但是,如果我删除此代码块,我会收到相同的警告。所以我想这不是我的问题。

这是我调用自定义钩子的函数:

import React from 'react';
import {
    Box,
    Text,
    Link,
    Container,
    useColorModeValue,
} from '@chakra-ui/react';
import { Helmet } from 'react-helmet-async';
import { Link as ReachLink } from 'react-router-dom';
import usePosts from '../hooks/FetchPosts';

function Thread() {
    const { thread, loading } = usePosts();

    console.log(thread);
    if (loading) {
        return <Text>{loading ? 'Loading...' : null}</Text>;
    }

    return (
        <Box>
            {thread.map((item) => (
                <Box key={item._id}>
                    <Helmet>
                        <meta charSet='utf-8' />
                        <title>{`Amicus - ${item.title}`}</title>
                    </Helmet>
                    <Container>
                        <Box>
                            <Text
                                as='h1'
                                fontSize='xx-large'
                                color={useColorModeValue('brand.100', 'gray.500')}
                            >
                                {item.title}
                            </Text>

                            <Link
                                to={`/post/?post=${item._id}`}
                                as={ReachLink}
                                style={{ textDecoration: 'none' }}
                            >
                                <Box
                                    key={item._id}
                                    border='1px'
                                    borderColor='gray.200'
                                    mt='3'
                                    p='4'
                                >
                                    <Text
                                        fontWeight='medium'
                                        color={useColorModeValue('brand.100', 'gray.500')}
                                    >
                                        {item.content}
                                    </Text>
                                    <Text
                                        fontWeight='medium'
                                        as='span'
                                        color={useColorModeValue('brand.100', 'gray.500')}
                                        mr='4'
                                    >
                                        Skrivet av: {item.user.username}
                                    </Text>
                                    <Text
                                        fontWeight='medium'
                                        as='span'
                                        color={useColorModeValue('brand.100', 'gray.500')}
                                        mr='4'
                                    >
                                        {item.postdate.slice(0, 10)}
                                    </Text>
                                    <Text
                                        fontWeight='medium'
                                        as='span'
                                        color={useColorModeValue('brand.100', 'gray.500')}
                                        mr='4'
                                    >
                                        {item.posts.length} svar
                                    </Text>
                                </Box>
                            </Link>
                        </Box>
                    </Container>
                </Box>
            ))}
        </Box>
    );
}


export default Thread;

这是我的自定义钩子:

import { useState, useEffect } from 'react';
import { useLocation } from 'react-router-dom';

const usePosts = () => {
    const [thread, setThread] = useState([]);
    const [loading, setLoading] = useState(true);
    const { search } = useLocation();

    useEffect(() => {
        const abortController = new AbortController();
        async function getData() {
            const URL = `http://localhost:5000/api/v1/categories/${search.slice(9)}`;
            try {
                const options = {
                    method: 'GET',
                    credentials: 'include',
                    signal: abortController.signal,
                };
                const fetchData = await fetch(`${URL}`, options);
                const res = await fetchData.json();
                setThread(res.data.categories.threads);
                setLoading(false);
            } catch (error) {
                if (error.name === 'AbortError') {
                    console.log('Leaving page before it rendered');
                }
                console.log(error);
            }
        }
        getData();
    }, [URL]);
    return { thread, loading };
};

export default usePosts;

标签: reactjsreact-hooks

解决方案


您需要从条件语句中提取所有挂钩调用

这是你的固定代码

import React from 'react';
import {
  Box,
  Text,
  Link,
  Container,
  useColorModeValue,
} from '@chakra-ui/react';
import { Helmet } from 'react-helmet-async';
import { Link as ReachLink } from 'react-router-dom';
import usePosts from '../hooks/FetchPosts';

function Thread() {
  const { thread, loading } = usePosts();
  const color = useColorModeValue('brand.100', 'gray.500');

  console.log(thread);
  if (loading) {
    return <Text>{loading ? 'Loading...' : null}</Text>;
  }

  return (
    <Box>
      {thread.map((item) => (
        <Box key={item._id}>
          <Helmet>
            <meta charSet='utf-8' />
            <title>{`Amicus - ${item.title}`}</title>
          </Helmet>
          <Container>
            <Box>
              <Text
                as='h1'
                fontSize='xx-large'
                color={color}
              >
                {item.title}
              </Text>

              <Link
                to={`/post/?post=${item._id}`}
                as={ReachLink}
                style={{ textDecoration: 'none' }}
              >
                <Box
                  key={item._id}
                  border='1px'
                  borderColor='gray.200'
                  mt='3'
                  p='4'
                >
                  <Text
                    fontWeight='medium'
                    color={color}
                  >
                    {item.content}
                  </Text>
                  <Text
                    fontWeight='medium'
                    as='span'
                    color={color}
                    mr='4'
                  >
                    Skrivet av: {item.user.username}
                  </Text>
                  <Text
                    fontWeight='medium'
                    as='span'
                    color={color}
                    mr='4'
                  >
                    {item.postdate.slice(0, 10)}
                  </Text>
                  <Text
                    fontWeight='medium'
                    as='span'
                    color={color}
                    mr='4'
                  >
                    {item.posts.length} svar
                  </Text>
                </Box>
              </Link>
            </Box>
          </Container>
        </Box>
      ))}
    </Box>
  );
}


export default Thread;

推荐阅读