使用 axios 和 Redux Saga 调用 API 总是返回 undefined
Posted
技术标签:
【中文标题】使用 axios 和 Redux Saga 调用 API 总是返回 undefined【英文标题】:Call API using axios and Redux Saga always return undefined 【发布时间】:2021-09-20 06:20:48 【问题描述】:我正在使用axios和redux saga调用api并检查本地输入,但是redux saga总是返回undefined
使用 axios 获取数据的功能
export function requestGetUser()
return axios(
method: 'get',
url: 'https://my-json-server.typicode.com/khanh21011999/demo/user',
);
动作文件
export const getUser = () => (
type: actionList.GET_USER,
);
export const setUser = (user) => (
type: actionList.SET_USER,
user,
);
export const GetUserInfo = (user, password) =>
return
type: actionList.GET_USER_INFO,
data: user, password,
;
export const LoginSuccess = (data) =>
return
type: actionList.LOGIN_SUCCESS,
data,
;
;
export const LoginFailed = (data) =>
return
type: actionList.LOGIN_FAIL,
data,
;
;
export const Logout = (data) =>
return
type: actionList.LOG_OUT,
data
;
;
Redux-saga 部分
我记录了所有内容,但它返回 undefined
export function* LoginsSagaFunc()
yield takeLatest('GET_USER_INFO', loginSaga)
function* SaveToAsyncStorage(data)
try
AsyncStorage.setItem(
'data',
JSON.stringify(
username: data.username,
password: data.password
))
catch (e)
console.log('error save to Storage');
function* loginSaga(action)
console.log('Saga is working')
const getJson = yield call(requestGetUser)
const getJsonData = JSON.parse(JSON.stringify(getJson))
const getJsonUsername = String(getJsonData.username)
console.log('JsonUsername '+getJsonUsername)
console.log("local data " + action.data.username)
console.log('getJsonData '+getJsonData)
console.log('GetJson '+getJson)
const getJsonPassword = String(getJsonData.password)
if (String(action.data.username) === getJsonUsername)
if (String(action.data.password) === getJsonPassword)
console.log('saga login success')
yield put(type: 'LOGIN_SUCCESS')
SaveToAsyncStorage(action.data)
else
console.log('saga password fail')
else
console.log("saga user fail")
减速器
const initStateAuth=
isAuth:false,
isLogIn:false
const AuthReducer =(state=initStateAuth,action)=>
switch (action.type)
case actionList.LOGIN_SUCCESS:
console.log('action : LOG IN SUCCESS');
return
isAuth: true,
isLogIn: true,
;
case actionList.GET_USER_INFO:
return initStateAuth
case actionList.LOGIN_FAIL:
return initStateAuth
case actionList.LOG_OUT:
return initStateAuth
default:
return state;
export default AuthReducer
我如何在主文件上分派
function LoginScreen(navigation)
// set timeout ID for setTimeOut()
const timeIdRef = React.useRef(null);
const dispatch = useDispatch();
const [username, getUsername] = useState('');
const [password, getPassword] = useState('')
// handleInput = (e) =>
// getUserInfo(e.target.value);
// ;
// mock user from fake api
useEffect(() =>
// dispatch(getUser());
, [dispatch]);
dispatch(GetUserInfo(username, password));
// const handlegetdata= (user,password)=>
// dispatch(GetUserInfo(user,password))
// //
// console.log(handleGetdata.user)
const user = useSelector((state) =>
return state.User.user;
);
// console.log('user' + username)
// console.log('userJSon'+user.username)
useEffect(() =>
return () =>
if (timeIdRef.current)
// make sure this is always cleared in case clearTo is never called
clearTimeout(timeIdRef.current);
;
, [timeIdRef]);
// console.log();
const Login = useSelector((state) =>
return state.LoginAction.loginStatus;
);
// console.log(Login)
// const initModal = false;
// eslint-disable-next-line require-jsdoc
function handleLogin()
dispatch(type: 'changeLogin');
function handlDefault()
dispatch(type: 'getDefault');
// not show??
// console.log(username);
// console.log('Login ' + Login)
// const [show, doShow] = useState(initModal);
// const [visible, UpdateView] = useState(false)
// Show modal dialog
// function ChangeModalValue()
// console.log(show);
// doShow(!show);
//
// setTimer after Model Appear
function SetTimer()
handleLogin();
if (timeIdRef.current)
// clear any previous timeIdRef to avoid multiple button click activate multiple setTimeout
clearTimeout(timeIdRef.current);
const timeID = setTimeout(() =>
navigation.navigate('Home');
, 3000);
timeIdRef.current = timeID;
function clearTO()
clearTimeout(timeIdRef.current);
timeIdRef.current = null;
handlDefault();
// make text black when check complete
function getTextStyle(isValid)
if (isValid)
return
color: 'black',
;
return
color: 'grey',
;
// function getLoginText()
// return <CirclesLoader />;
//
// function hideText(visible)
// if(isDisabler)
//
const loginValidationSchema = Yup.object().shape(
email: Yup.string().email('Please enter valid email').required('Email Address is Required'),
password: Yup.string()
.min(8, (min) => `Password must be at least $min characters`)
.required('Password is required'),
);
return (
<View style=styles.ViewStyle>
<Text style=fontSize: 40>Login To System</Text>
<Formik
validateOnMount
validationSchema=loginValidationSchema
initialValues=email: '', password: ''
onSubmit=value =>
getUsername(value.email)
getPassword(value.password)
SetTimer()
// () => navigation.navigate('Login')
>
(handleChange, handleBlur, handleSubmit, values, errors, touched, isValid) => (
<View>
<TextInput
name="email"
placeholder="Email Address"
style=styles.TextInputForm
onChangeText=handleChange('email')
onBlur=handleBlur('email')
value=values.email
keyboardType="email-address"
/>
errors.email && touched.email && <Text style=styles.errorText>errors.email</Text>
<TextInput
name="password"
placeholder="Password"
onChangeText=handleChange('password')
onBlur=handleBlur('password')
value=values.password
secureTextEntry
style=styles.TextInputForm
/>
errors.password && touched.password && (
<Text style=styles.errorText>errors.password</Text>
)
<TouchableOpacity
onPress=handleSubmit
style=styles.ButtonLogin
disabled=!isValid || values.email === ''>
/* <CirclesLoader size=20 dotRadius=7 /> */
<Text style=getTextStyle(isValid)>Login</Text>
</TouchableOpacity>
<View>
<Modal transparent visible=Login>
<View
style=
backgroundColor: '#000000',
flex: 1,
justifyContent: 'center',
alignContent: 'center',
>
<View style=styles.ModalStyle>
<CirclesLoader />
<TextLoader
textStyle=
fontSize: 25,
marginTop: 20,
text="Logging you in"
/>
<TouchableOpacity onPress=clearTO style=styles.ButtonBack>
<Text>Go back</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
</View>
</View>
)
</Formik>
</View>
);
另外,当我按下时,动作会获取数据,但它在 redux-saga 部分返回未定义,所以用户名总是如此相等,发生了什么??
为什么数据显示在 redux 调试器中,但我在 saga 上看不到,为什么我从 axios 获取的数据返回未定义?
一个简短的 gif 来显示发生了什么
请帮忙,万分感谢
完整代码:https://codesandbox.io/s/github/khanh21011999/Trainning-react-native
【问题讨论】:
【参考方案1】:首先,您的沙盒无法正常工作,因此请确保它适用于所有人。
第二次尝试在您的代码中像这样使用 async/await,我无法测试它,因为您的沙箱正在崩溃。
export async function requestGetUser() return await axios.get('https://my-json-server.typicode.com/khanh21011999/demo/user');
【讨论】:
对不起,我使用的是 react-native,所以只显示代码,但我不知道如何让它们在 web 上运行 :(( 我试过你的方法,但它显示如下ibb.co/d2BtSQg 当您显式调用get
时,为什么要使用方法和 url 属性传递对象,只需按照我在答案中写的方式尝试 axios。
或者你可以简单地忽略 async/await 并返回 then 和 catch 块。
我想我会选择更简单的方法,我刚刚开始学习 react 和 react native 3 周,没有网络背景,这对我来说太重要了,但感谢你的回答,我很感激那【参考方案2】:
在 axios API 调用中,您需要对成功或失败的响应进行编码,如下所示:
export function requestGetUser()
return axios(
method: 'get',
url: 'https://my-json-server.typicode.com/khanh21011999/demo/user',
)
.done (function(data)
//Get your data here upon successful fetch
)
.fail (function()
console.log("Failed to fetch data");
)
.always (function()
console.log("This function always executes whether success or fail");
);
【讨论】:
谢谢你的回答,但是我如何获取function(data)
中的数据,我的意思是,如何访问redux-saga文件中的这些数据,我很新,请举个例子
如何获取这些数据? return data
合法吗?
但是当我使用console.log ibb.co/r5xFjF3时显示成功
请帮忙,我被这个问题困扰了好几天:((
嗨庆。您应该通过在函数内部编码从 .done 函数本身获取数据。您可以在那里执行 console.log(data) 来查看数据(data[0].fieldname、data[1].fieldname...等)。还有其他方法,例如将数据放入全局变量中,这不是一个好方法。以上是关于使用 axios 和 Redux Saga 调用 API 总是返回 undefined的主要内容,如果未能解决你的问题,请参考以下文章
酶集成测试:axios.get 调用未在 redux-saga 中执行
插入并放入nodeJs + express api时,带有Redux Saga的Axios不发送表单数据