Reputation: 605
I'm using axios and redux saga to call api and check with local input, but redux saga always return undefined
Function to get data using axios
export function requestGetUser() {
return axios({
method: 'get',
url: 'https://my-json-server.typicode.com/khanh21011999/demo/user',
});
}
Action file
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 part
I log everything but it return 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")
}
}
The reducer
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
How i dispatch on the main file
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>
);
}
Also, the action get the data when i press, BUT it return undefined in redux-saga part, so username always so equal, what happened??
Why data show in redux debugger but i can't see it on saga, and why data i fetch from axios return undefinded?
a short gif to show what happened
FULL CODE : https://codesandbox.io/s/github/khanh21011999/Trainning-react-native
Upvotes: 0
Views: 1762
Reputation: 667
First of all your sandbox is not working so make sure it works for all.
Second try using async/await like this in your code, I'm not able to test it because your sandbox is crashing.
export async function requestGetUser() { return await axios.get('https://my-json-server.typicode.com/khanh21011999/demo/user'); }
Upvotes: 0
Reputation: 557
In the axios API call, you need to code for a successful or a failed response as follows:
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");
});
}
Upvotes: 1