为什么 useReducer 不更新 React 上下文中的状态
Why useReducer doesn't update state in React context
我正在使用 useReducer 和上下文来更新我在 App.js 中的状态,然后将数据发送到数据库,但它不会更新状态并且始终为空。
App.js
import AuthContext from './context';
import screenA from './screenA';
export default function App() {
const initialLoginState = {
email: null,
};
const loginReducer = (prevState, action) => {
switch (action.type) {
case 'Email':
return {
...prevState,
email: action.Email,
};
}
};
const authContext = React.useMemo(
() => ({
email: emailUser => {
dispatch({type: 'Email', Email: emailUser});
console.log(loginState.email);
},
signIn: async () => {
try {
fetch('FakeApi', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: loginState.email,
date: '2021-9-20',
}),
});
} catch (e) {
console.log(e);
}
},
}),
[],
);
const [loginState, dispatch] = React.useReducer(
loginReducer,
initialLoginState,
);
return (
<AuthContext.Provider value={authContext}>
<screenA />
</AuthContext.Provider>
Blockquote context
我创建了一个单独的上下文组件
context.js
import React from 'react';
export const AuthContext = React.createContext();
Blockquote screenA
在 screenA 中,我使用电子邮件和登录将数据发送到 App.js,然后将这些数据保存在数据库中
screenA.js
import {AuthContext} from './context';
function screenA() {
const {email,signIn} = React.useContext(AuthContext);
return (
<View style={{marginTop: 150}}>
{/* Count: {state.count} */}
<Button
title="sent email"
onPress={() => {
email('example@gmail.com');
}}
/>
<Button
title="signIn"
onPress={() => {
signIn();
}}
/>
</View>
);
}
export default screenA;
需要注意的几点:
- reducer 应该总是 return 状态对象(将
default
case 添加到 switch)
- 最好在action中传一个叫
payload
的属性,以免出错
- 提供者需要一个对象
value
(添加另一组{})
尝试像这样更改您的代码:
const loginReducer = (prevState, action) => {
switch (action.type) {
case 'Email':
return {
...prevState,
email: action.payload,
};
default:
return prevState
}
};
const authContext = React.useMemo(
() => ({
email: emailUser => {
dispatch({type: 'Email', payload: emailUser});
console.log(loginState.email);
},
...
}),
[],
);
return (
<AuthContext.Provider value={{authContext}}>
<screenA />
</AuthContext.Provider>
正在更新状态,问题是您试图在“调度”后立即将值写入控制台,而此时状态尚未更新。如果要查看更新后的值,将这个useEffect添加到App.js
useEffect(() => {
console.log(loginState.email);
}, [loginState.email]);
这个useEffect会在“loginState.email”变化时触发。
您应该考虑使用 React Developer Tools 来验证状态更改。
我正在使用 useReducer 和上下文来更新我在 App.js 中的状态,然后将数据发送到数据库,但它不会更新状态并且始终为空。
App.js
import AuthContext from './context';
import screenA from './screenA';
export default function App() {
const initialLoginState = {
email: null,
};
const loginReducer = (prevState, action) => {
switch (action.type) {
case 'Email':
return {
...prevState,
email: action.Email,
};
}
};
const authContext = React.useMemo(
() => ({
email: emailUser => {
dispatch({type: 'Email', Email: emailUser});
console.log(loginState.email);
},
signIn: async () => {
try {
fetch('FakeApi', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: loginState.email,
date: '2021-9-20',
}),
});
} catch (e) {
console.log(e);
}
},
}),
[],
);
const [loginState, dispatch] = React.useReducer(
loginReducer,
initialLoginState,
);
return (
<AuthContext.Provider value={authContext}>
<screenA />
</AuthContext.Provider>
Blockquote context
我创建了一个单独的上下文组件
context.js
import React from 'react';
export const AuthContext = React.createContext();
Blockquote screenA
在 screenA 中,我使用电子邮件和登录将数据发送到 App.js,然后将这些数据保存在数据库中 screenA.js
import {AuthContext} from './context';
function screenA() {
const {email,signIn} = React.useContext(AuthContext);
return (
<View style={{marginTop: 150}}>
{/* Count: {state.count} */}
<Button
title="sent email"
onPress={() => {
email('example@gmail.com');
}}
/>
<Button
title="signIn"
onPress={() => {
signIn();
}}
/>
</View>
);
}
export default screenA;
需要注意的几点:
- reducer 应该总是 return 状态对象(将
default
case 添加到 switch) - 最好在action中传一个叫
payload
的属性,以免出错 - 提供者需要一个对象
value
(添加另一组{})
尝试像这样更改您的代码:
const loginReducer = (prevState, action) => {
switch (action.type) {
case 'Email':
return {
...prevState,
email: action.payload,
};
default:
return prevState
}
};
const authContext = React.useMemo(
() => ({
email: emailUser => {
dispatch({type: 'Email', payload: emailUser});
console.log(loginState.email);
},
...
}),
[],
);
return (
<AuthContext.Provider value={{authContext}}>
<screenA />
</AuthContext.Provider>
正在更新状态,问题是您试图在“调度”后立即将值写入控制台,而此时状态尚未更新。如果要查看更新后的值,将这个useEffect添加到App.js
useEffect(() => {
console.log(loginState.email);
}, [loginState.email]);
这个useEffect会在“loginState.email”变化时触发。
您应该考虑使用 React Developer Tools 来验证状态更改。