我正在构建一个移动应用,并且我正在使用Django REST Framework作为后端。而且我也在使用Redux。我正在使用的API之一是验证OTP代码。如果OTP代码匹配,那么无论这是否是新用户,我都将根据服务器的响应进行调整。如果是新用户,则将其重定向到注册屏幕,如果不是新用户,则将其重定向到登录屏幕,这是我的问题。
我将服务器的响应存储在redux存储中名为isNewUser的变量中。然后,我使用useSelector在组件内部访问它。输入OTP代码后,单击按钮时,我将分派两个动作。首先验证OTP的人。第二个要么是用于登录的调度,要么是用于注册操作的调度,这取决于我从redux存储中获取的isNewUser变量。
问题是,当我分派第一个动作(即对OTP进行验证并存储isNewUser变量)时,直到下一次渲染时,该变量的值才会在我的组件中更新,因此我无法分派第二个动作,直到再次单击该按钮,以便更新变量的值。
那么如何解决呢?我不知道我的实现是否正确,或者有更好的实现。
这是我的操作代码,我尚未编写用于登录和注册操作的代码
export const validateOTP = (otp, mobileNum) => {
return async dispatch => {
const response = await fetch("http://localhost:8000/api/validate_otp", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
otp: otp,
mobile: mobileNum
})
});
if (!response.ok) {
const errorResData = await response.json();
console.log(errorResData);
}
const resData = await response.json();
if (resData.status === false) {
throw new Error(resData.detail);
} else {
const isNewUser = resData.isNewUser;
dispatch({
type: VALIDATE_OTP,
isNewUser: isNewUser
});
}
};
};
这是我的减速器代码:
import { VALIDATE_OTP } from "../actions/auth";
const initialState = {
isNewUser: null
};
export default (state = initialState, action) => {
switch (action.type) {
case VALIDATE_OTP: {
const isNewUserVal = action.isNewUser;
return {
...state,
isNewUser: isNewUserVal
};
}
}
return state;
};
这是来自React Native组件的示例代码:
const CodeEntryScreen = props => {
const dispatch = useDispatch();
const isNewUser = useSelector(state => state.auth.isNewUser)
const [error, setError] = useState();
useEffect(() => {
if (error) {
Alert.alert("An Error Occurred", error, [{ text: "Okay" }]);
}
}, [error]);
const validateOTPHandler = async () => {
setError(null);
try {
await dispatch(authActions.validateOTP(otp, mobileNum));
console.log(isNewUser)
if(isNewUser) {
// dispatch resgister action
}
else {
// dispatch login action
}
} catch (err) {
setError(err.message);
}
};
答案 0 :(得分:1)
您可以稍做修改即可解决此问题。较容易的是这样:
dispatch
中使用validateOTPHandler
返回值在您的validateOTP
函数中,您将在结尾处添加以下内容:
dispatch({
type: VALIDATE_OTP,
isNewUser: isNewUser
});
让您的函数返回该值:
return dispatch({
type: VALIDATE_OTP,
isNewUser: isNewUser
});
有了这一更改,您就可以在组件中通过以下方式访问操作的负载:
const validateOTPHandler = async () => {
setError(null);
try {
const { isNewUser: isNew } = await dispatch(authActions.validateOTP(otp, mobileNum));
console.log(isNew)
if(isNew) {
// dispatch resgister action
}
else {
// dispatch login action
}
} catch (err) {
setError(err.message);
}
};
这是更轻松的更改,可以根据需要进行操作。
useEffect
我认为这与您想到的流程更相似:
但是,您需要使用useEffect
来监听通过这种方式所做的更改:
const CodeEntryScreen = props => {
const dispatch = useDispatch();
const isNewUser = useSelector(state => state.auth.isNewUser)
const [error, setError] = useState();
const [success, setSuccess] = useState(false); // true when validateOTP succeeds
useEffect(() => {
if (error) {
Alert.alert("An Error Occurred", error, [{ text: "Okay" }]);
}
}, [error]);
useEffect(() => {
if (success) {
// validateOTP succeed... let's check isNewUser :)
if (isNewUser) {
// dispatch register
} else {
// dispatch login
}
}
}, [success, isNewUser]);
const validateOTPHandler = async () => {
setError(null);
setSuccess(false);
try {
await dispatch(authActions.validateOTP(otp, mobileNum));
setSuccess(true);
} catch (err) {
setError(err.message);
}
};