我有一個奇怪的情況,狀態變數在一個組件中成功更新,但在另一個組件中沒有。我成功地更改了state,因為我可以看到它反映在我觸發dispatch. 但是在另一個包裹在同一個 中的組件中Provider,我看不到任何變化。
其他 Stack Overflow 答案似乎主要建議不要直接 改變 state,但在這里我沒有這樣做 - 我正在調度一個操作來更新狀態,類似于您在 Redux 語法中看到的內容。
代碼沙盒演示
TeaSettingsContext.tsx
const TeaSettingsContext = createContext<{ state: State; dispatch: Dispatch } | undefined>(undefined);
const teaSettingsReducer = (state: State, action: Action) => {
switch (action.type) {
case TeaSettingsActions.ChooseTea: {
return { ...state, chosenTea: action.payload };
}
case TeaSettingsActions.ChangeStrength: {
return { ...state, desiredStrength: action.payload };
}
default: {
throw new Error(`Unhandled action type: ${action.type}`);
}
}
};
export function TeaSettingsProvider({
children,
}: TeaSettingsProviderProps): Context {
const [state, dispatch] = useReducer(teaSettingsReducer, {
chosenTea: {},
desiredStrength: 0.5,
});
return (
<TeaSettingsContext.Provider value={{ state, dispatch }}>
{children}
</TeaSettingsContext.Provider>
);
}
export const useTeaSettingsContext = (): TeaSettingsContext => {
const context = useContext(TeaSettingsContext);
if (context === undefined) {
return;
}
return context;
};
這是“成功”的組成部分:
主頁.tsx
<TeaSettingsProvider>
<StrengthSlider />
</TeaSettingsProvider>
強度滑塊.tsx
export default function StrengthSlider(): ReactNode {
const { state, dispatch } = useTeaSettingsContext();
console.log(state.desiredStrength) // logs the increment on each press.
const incrementStrength = () => {
dispatch({
payload: state.desiredStrength 0.1,
type: "change-strength",
});
};
return (
<Box position="relative" w="100%">
<Button title="Press" onPress={incrementStrength} />
<Text>{state.desiredStrength}</Text>
</Box>
);
}
...并且不成功的重新渲染發生在此組件中:
茶頁.tsx
const Component = () => {
if (type === "tea") {
return data.map((teaObj) => (
<TeaCard id={teaObj.id} teaData={teaObj.data} key={teaObj.id} />
));
}
};
return (
<TeaSettingsProvider>
<Component />
</TeaSettingsProvider>
);
茶卡.tsx
export function TeaCard({ id, teaData }: TeaCardProps): ReactNode {
const { state, dispatch } = useTeaSettingsContext();
console.log(state.desiredStrength); // this always logs the starting value of 0.5 and doesn't log each time I press the button above.
// ...
}
僅供參考:我的代碼基于 Kent C Dodds 的文章:https : //kentcdodds.com/blog/how-to-use-react-context-effectively
uj5u.com熱心網友回復:
我認為您有點誤解了背景關系的作業原理。
基本上(如反應檔案所建議的那樣):
每個 Context 物件都帶有一個 Provider React 組件,該組件允許消費組件訂閱背景關系更改。
Provider 組件接受要傳遞給作為此 Provider 后代的消費組件的 value prop。一個提供者可以連接到多個消費者。提供者可以嵌套以覆寫樹中更深層次的值。
每當 Provider 的 value 屬性發生變化時,所有作為 Provider 后代的消費者都會重新渲染。從 Provider 到其后代消費者(包括 .contextType 和 useContext)的傳播不受 shouldComponentUpdate 方法的影響,因此即使祖先組件跳過更新,消費者也會更新。
簡而言之,當您創建一個具有值的提供者時,您可以從多個消費者(需要是該提供者的孩子)訪問該資訊。到現在為止還挺好。
除了:
Home.tsx并且TeaPage.tsx都初始化背景關系的不同實體(因此每個實體都有自己的提供者)。為了解決這個問題,您應該只在同時是Home和 的父組件中創建一個提供程式TeaPage。
React 背景關系不能作為 redux(你有一個可以從任何地方訪問的全域存盤)。它讓您可以選擇為大組件(在子組件中使用)創建背景關系(使用可重用資料)。
另請注意開頭參考的最后一段:基本上當背景關系發生變化時,這會導致所有消費者重新渲染(有時可能會導致一些性能問題),因此請明智地使用它。這是一篇關于此的簡短文章。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/334693.html
標籤:javascript 反应 反应原生 状态 反应状态管理
下一篇:從組件呼叫函式
