【发布时间】:2021-01-06 21:44:31
【问题描述】:
我正在尝试了解 Context API 如何与 React 挂钩(特别是 useEffect 和 useReducer)一起工作。
我不确定为什么我的一个组件 (ContactListPage) 似乎要渲染两次。
演示的最小示例:
index.js
ReactDOM.render(
<ContactContextProvider>
<BrowserRouter>
<App />
</BrowserRouter>
</ContactContextProvider>,
document.getElementById("root")
);
contact-context.js
export const ContactContext = createContext();
function reducer(state, action) {
switch (action.type) {
case "FETCH_CONTACTS": {
return { ...state, contacts: action.payload };
}
default:
throw new Error();
}
}
export const ContactContextProvider = (props) => {
const [state, dispatch] = useReducer(reducer, { contacts: [] });
const store = React.useMemo(() => ({ state, dispatch }), [state, dispatch]);
return (
<ContactContext.Provider value={store}>
{props.children}
</ContactContext.Provider>
);
};
ContactListPage.js
export default function ContactListPage() {
const { state, dispatch } = useContext(ContactContext);
console.log(state);
useEffect(() => {
const fetchData = async () => {
try {
// Make Ajax request for contacts here
dispatch({
type: "FETCH_CONTACTS",
payload: [{ name: "Bob" }]
});
} catch (error) {
// handle error
}
};
fetchData();
}, []); // eslint-disable-line react-hooks/exhaustive-deps
return (
<div>
<h1>List of Contacts</h1>
</div>
);
}
这里是the app running in a CodeSandbox。
ContactListPage 组件首次渲染时,控制台会记录以下内容:
Object {contacts: Array[0]}
Object {contacts: Array[1]}
这对我来说很有意义。最初contacts 数组是空的,然后在ContactListPage 组件的useEffect 钩子中,我调度了一个动作来添加一个联系人,因此该组件使用更新的联系人列表重新渲染。
当我离开这个视图(我正在使用 React 路由器),然后我导航回来时,问题就出现了。在这种情况下,我看到:
Object {contacts: Array[1]}
Object {contacts: Array[1]}
我原以为 console.log 语句只会触发一次,因为联系人数组没有改变。
我整个下午都在谷歌上搜索这个。我在 SO 上找到的其他答案都没有对我有用。
那么,我的问题是:为什么console.log 语句总是触发两次?
注意要在 CodeSandbox 中重现此内容:
- 单击添加联系人链接并观察 CodeSandbox 控制台中的第一个输出。
- 单击联系人列表链接并观察 CodeSandbox 控制台中的第二个输出。
【问题讨论】:
标签: javascript reactjs use-effect react-context