Почему не происходит ререндер компонента в React?
Описание
Есть компоненты: A, B, C
Компонент А:
export default function A() {
const [activeConversationId, setActiveConversationId] = useState<string>("");
return (
<>
<B
activeConversationId={activeConversationId}
/>
{!activeConversationId && <C onClickNew={(conversationId) => setActiveConversationId(conversationId)} />}
</>
);
Компонент B:
export default function B({ activeConversationId }) {
const { conversations = [] } = useConversations();
useEffect(() => {
console.log('CONVERSATION LIST', conversations);
}, [conversations]);
return (
<>
{conversations.map((conversation) => (
<Group key={conversation.id} justify='space-between' style={{ marginRight: '5%' }} >
{conversation.id}
</Group>
))}
</>
);
}
Компонент C:
export default function C({ onClickNew }: IConversationNew) {
const { db, write } = useLowDb();
const [createConversationId, setCreateConversationId] = useState<boolean>(false);
useEffect(() => {
if (!(db && createConversationId)) {
return;
}
const conversation: Conversation = { id: getRandomId(), messages: [] };
console.log('NEW');
db.conversation.push(conversation);
write();
onClickNew(conversation.id);
setCreateConversationId(false);
}, [createConversationId, db]);
return (
<>
<Button
size="xl"
variant="outline"
onClick={() => setCreateConversationId(true)}
>
<IconPlus size={48} />
</Button>
</>
);
};
Также есть два кастомных хука:
useLowDb
export default function useLowDb() {
const [loading, setLoading] = useState<boolean>(true);
const [database, setDatabase] = useState<InitializedDb>();
const [data, setData] = useState<InitData>();
const getAPIData = async () => {
setLoading(true);
const database = await lowdbInstance.getDb();
setDatabase(database);
setData(database.data);
setLoading(false);
};
useEffect(() => {
getAPIData();
}, []);
const write = () => {
if (!database) {
return;
}
database?.write();
setData(structuredClone(data));
console.log('LOWDB', data?.conversation);
};
return {
loading,
db: data,
write,
};
}
useConversations:
export default function useConversations() {
const { db } = useLowDb();
const [loading, setLoading] = useState<boolean>(true);
const [conversations, setConversations] = useState<Conversation[]>();
useEffect(() => {
setLoading(true);
if (!db) {
return;
}
setConversations(structuredClone(db.conversation));
console.log('CONVETSATION LIST', db.conversation);
setLoading(false);
}, [db]);
return {
loading,
conversations,
};
}
Идея такая:
- Компонент А является родителем для B И C.
- Компонент B рендерит список комнат из хука
useConversations
. - Компонент С Создает комнату и вызывает
write
у хукаuseLowDb()
.
Ожидаемое поведение:
Компонент С модифицирует useLowDb
, что должно вызвать цепную реакцию, обновить useConversations
, а он обновит компонент B. После этого выполнится {conversations.map((conversation) => (
в компоненте B. В результате в списке будет новая комната.
Реальная ситуация:
В компоненте B, в useEffect:
useEffect(() => {
console.log('CONVERSATION LIST', conversations);
}, [conversations]);
Я вижу обновленные данные. Но {conversations.map((conversation) => (
не отрабатывает. И новая комната не рендерится.
В чем проблема?