组件在 setState 后未触发重新渲染

问题描述 投票:0回答:1

我有两个组件。 1 是一个钩子,第二个是映射元素数组并渲染它们的功能组件。

这是 useRooms 挂钩中的代码:

import { useCallback, useEffect, useState } from "react";
import { IRoom } from "@types";
import methods from "@api:methods";
import { useStoreState } from "../store.tsx";

const useRooms = (id: number) => {
    const setState = useStoreState()[1];

    const [loading, setLoading] = useState(true);
    const [rooms, setList] = useState<IRoom[]>([]);

    const addRoom = (room: IRoom) => {
        setList((prevState) => [room, ...prevState]);
    };

    useEffect(() => {
        setState((prevState) => ({ ...prevState, addRoom }));
    }, []);

    const handleRefresh = useCallback(
        async (startLoading?: boolean) => {
            if (startLoading) setLoading(true);
            const data = await methods.service.rooms.list(id);
            setLoading(false);

            if (!data) {
                return false;
            }

            setList(data);
        },
        [setList, id]
    );

    useEffect(() => {
        setList([]);
        handleRefresh(true).then();
    }, [id]);

    const handleCreate = useCallback(
        async (name: string) => {
            setLoading(true);
            const data = await methods.service.rooms.add(id, name);
            setLoading(false);

            if (!data) {
                console.error("Помилка", "Не вдалося створити точку");
                setLoading(false);
                return false;
            } else {
                setList((prevRooms) => {
                    const updatedRooms = [data, ...prevRooms];
                    console.log("Updated Rooms in useRooms:", updatedRooms);
                    console.log(
                        "Previous Rooms Reference:",
                        prevRooms === updatedRooms
                    );
                    return updatedRooms;
                });
                return data;
            }
        },
        [id]
    );

    return {
        loading,
        handleRefresh,
        rooms,
        handleCreate,
    };
};

export default useRooms;

当我添加一个新房间时,它会触发handleCreate回调,并在其中我在setList中设置新的房间数组,因此“房间”正在更新。

 const handleCreate = useCallback(
        async (name: string) => {
            setLoading(true);
            const data = await methods.service.rooms.add(id, name);
            setLoading(false);

            if (!data) {
                console.error("Помилка", "Не вдалося створити точку");
                setLoading(false);
                return false;
            } else {
                setList((prevRooms) => {
                    const updatedRooms = [data, ...prevRooms];
                    console.log("Updated Rooms in useRooms:", updatedRooms);
                    console.log(
                        "Previous Rooms Reference:",
                        prevRooms === updatedRooms
                    );
                    return updatedRooms;
                }); 
                return data;
            }
        },
        [id]
    );

但不会触发使用该hook的List功能组件的重新渲染。为什么会这样?

import { FC, useEffect } from "react";
import styled from "styled-components";
import { token } from "@atlaskit/tokens";
import Spinner from "@atlaskit/spinner";
import useRooms from "../../hooks/useRooms.tsx";
import { useLocalState } from "../../store.tsx";
import Room from "./Room.tsx";

const List: FC = () => {
    const { object } = useLocalState();
    const { rooms, loading } = useRooms(object.id);

    useEffect(() => {
        console.log(rooms);
    }, [rooms]);

    return (
        <Container>
            <HeaderContainer>
                {loading ? (
                    <Spinner size={"large"} />
                ) : (
                    <HeadTitle>{rooms.length} комнат</HeadTitle>
                )}
            </HeaderContainer>
            <ListContainer>
                {rooms.map((room) => (
                    <Room key={room.id} room={room} />
                ))}
            </ListContainer>
        </Container>
    );
};

const Container = styled.div`
    display: flex;
    flex-direction: column;
    border: 1px solid ${token("color.border")};
    border-radius: 6px;
`;

const HeaderContainer = styled.div`
    padding: 12px 13px;
    box-sizing: border-box;
    border-bottom: 1px solid ${token("color.border")};
`;

const HeadTitle = styled.span`
    font-size: 14px;
    font-weight: 500;
`;

const ListContainer = styled.div`
    overflow-y: auto;

    & > :not(:last-child) {
        border-bottom: 1px solid ${token("color.border")};
    }
`;

export default List;

javascript reactjs redux react-hooks
1个回答
0
投票

您面临的问题可能与您在 useRooms 挂钩中更新房间状态的方式有关。当您使用新数组调用 setList 时,React 不会自动触发使用此钩子的组件的重新渲染。 为了确保 List 组件在房间状态发生变化时重新渲染,您可以尝试以下操作:

当房间状态发生变化时,使用 useEffect 钩子触发重新渲染:

然后喜欢 常量列表: FC = () => {

const { object } = useLocalState();
const { rooms, loading } = useRooms(object.id);

useEffect(() => {
    console.log(rooms);
}, [rooms]);

return (
    // ... 
);
© www.soinside.com 2019 - 2024. All rights reserved.