通过在上下文中传递的函数,React状态始终具有初始值



我正在更新我从一个组件传递给它的父组件,然后通过上下文的函数。我可以随心所欲地设置状态,但我不能在这些函数中访问它的数据。它们显示为初始数据。这很奇怪,我检查了React DevTools,状态很好。

这是一个codeSandbox: https://codesandbox.io/s/admiring-fog-2b5gm?file=/components/Provider.tsx:859-992链接到页面:https://2b5gm.sse.codesandbox.io/

import React, { useState, createContext } from "react";
import Provider from "./Provider";
import Consumer from "./Consumer";
export const context = createContext<AppContextType | undefined>(undefined);
type AppContextType = {
actions: {
addStrings?: (t: string[]) => void;
logStrings?: () => void;
};
};
const TestContainer = () => {
const [actions, setActions] = useState<{
addStrings?: (t: string[]) => void;
}>({});
return (
<context.Provider
value={{
actions: actions
}}
>
<Provider setActions={setActions} />
<Consumer />
</context.Provider>
);
};
export default TestContainer;
import React, { useEffect, useState } from "react";
type ProviderProps = {
setActions: React.Dispatch<
React.SetStateAction<{
addStrings?: (t: string[]) => void;
logStrings?: () => void;
}>
>;
};
const Provider = ({ setActions }: ProviderProps) => {
const [textArray, setTextArray] = useState<string[]>([]);
function addStrings(texts: string[]) {
console.log("PREVIOUS LINES: ", textArray);
console.log("NEW LINES:", [...textArray, ...texts]);
setTextArray([...textArray, ...texts]);
}
function logStrings() {
console.log("Strings : ", textArray);
}
useEffect(() => {
console.log("send functions to parent");
setActions({ addStrings: addStrings, logStrings: logStrings });
}, []);
useEffect(() => {
console.log("useEffect textArray changed to: ", textArray);
}, [textArray]);
return (
<>
<h1>Strings : </h1>
{textArray.map((line, index) => (
<p key={index}>{line}</p>
))}
</>
);
};
export default Provider;
import React, { useContext } from "react";
import { context } from "./TestContainer";
const Consumer = () => {
const appContext = useContext(context);
function onButtonAddClick() {
if (appContext?.actions.addStrings)
appContext.actions.addStrings(["test 1", "test 2", "test 3"]);
}
function onButtonLogClick() {
if (appContext?.actions.logStrings) appContext.actions.logStrings();
}
return (
<div>
<button onClick={onButtonAddClick}>Add strings</button>
<button onClick={onButtonLogClick}>Log</button>
</div>
);
};
export default Consumer;

所讨论的数据是Provider组件中的textArray状态。我从Consumer组件调用addStringsLogStrings方法来控制它。

预期行为:LogStrings应该记录状态的实际值。在这种情况下:测试1,测试2,测试3;但是它总是打印状态的默认值。

您看到初始状态被记录的原因是因为setActions只在Provider首次挂载时被调用,而textArray仍然具有空数组[]的初始值。这将是logStrings将记录的值,即使您从外部更改了textArray

要用addStrings(["test 1", "test 2", "test 3"])传递的新textArray值实际更新logStrings,您需要再次调用setActions。这意味着将textArray添加到调用setActionsuseEffect的依赖项数组中。

useEffect(() => {
console.log("send functions to parent");
setActions({ addStrings: addStrings, logStrings: logStrings });
}, [textArray]);

最新更新