Reputation: 585
Problem:
I have created a react native application in there I have created the store using redux-thunk middleware. Now I am going to say How I have organized my code. in the actions folder, I have created an action file. This is the code of it.
import * as API from './httpClient';
import * as endPoints from './endpoints';
export const SEND_OTP = 'otp/SEND_OTP';
export const SEND_OTP_SUCCESS = 'otp/SEND_OTP_SUCCESS';
export const SEND_OTP_FAILD = 'otp/SEND_OTP_FAILD';
const sendOtpActionCreator = (value) => {
return (dispatch) => {
return API.Post(endPoints.SEND_OTP, {data: value})
.then((data) => {
dispatch(SEND_OTP_SUCCESS, data);
})
.catch((err) => {
dispatch(SEND_OTP_FAILD, err);
});
};
};
export default {
sendOtpActionCreator: sendOtpActionCreator,
};
HTTP client and endpoints file looks like this.
import I18n from 'react-native-i18n';
const REST_API = 'myapi';
const getCulture = () => {
let locale;
locale = I18n.locale;
if (locale === 'en') {
return 'en-us';
} else if (locale === 'si') {
return 'si-lk';
} else if (locale === 'ta') {
return 'ta-lk';
}
};
export const SEND_OTP = `${REST_API}/${getCulture()}/api/user/send/otp`;
this is how my HTTP client file is.
import axios from 'axios';
axios.defaults.headers.post['Content-Type'] = 'application/json';
var instance = null;
export const setHeader = async () => {
// const token = await AsyncStorage.getItem('jwt');
instance = axios.create({
baseURL: '',
timeout: 150000,
headers: {
// Authorization: 'Bearer ' + token,
'Content-Type': 'application/json',
},
});
instance.interceptors.response.use(
function (response) {
return response;
},
async function (error) {
if (error.response.status) {
if (error.response.status === 401) {
error = 'Unauthorised';
return error;
} else {
return error;
}
} else {
console.log(error);
}
},
);
};
export const Get = (route, data) => {
function getData() {
return instance.get(
route,
data == null ? {data: {}} : {data: JSON.stringify(data)},
);
}
if (instance) {
return getData();
}
return setHeader().then(getData);
};
export const Post = (route, data) => {
function postData() {
return instance.post(route, JSON.stringify(data));
}
if (instance) {
return postData();
}
return setHeader().then(postData);
};
Then I have export actions like this in index.js file of actions folder. This is the code of It.
import * as signin from './signin';
export {signin as signinTypes};
export const signinActions = signin.default;
Then I have created the reducer like this.
import {signinTypes as types} from '_store/actions';
const signin = (
state = {
success: false,
hasError: false,
error: '',
otp: '',
},
action,
) => {
console.log(action);
switch (action.type) {
case types.SEND_OTP:
return Object.assign({}, ...state, {hasError: false, error: {}});
case types.SEND_OTP_SUCCESS:
return Object.assign({}, ...state, {success: true});
case types.SEND_OTP_FAILD:
return Object.assign({}, ...state, {error: true});
default:
return state;
}
};
export default sign-in;
Then I have imported it in combined Reducer like this.
import {combineReducers} from 'redux';
import SignInReducer from '_store/reducers/signin';
const reducers = combineReducers({
signin: SignInReducer,
});
export default reducers;
And I have used action in my component file like this.
import { connect } from "react-redux";
import { signinActions } from "_store/actions";
const _onPress = (values, navigation, sendOTP) => {
console.log(values.mobileNo);
sendOTP(values.mobileNo);
// navigation.navigate('Otp');
};
const Login = (props) => {
return (
<View style={styles.formContainer}>
<Formik
initialValues={{
mobileNo: "",
toggle: true,
}}
validationSchema={Yup.object({
mobileNo: Yup.string().required("Mobile number required"),
})}
onSubmit={(values, formikActions) => {
_onPress(values, props.navigation, props.sendOTP);
setTimeout(() => {
formikActions.setSubmitting(false);
}, 500);
}}
>
{(formprops) => (
<View>
<View>
<TextInput
style={styles.textField}
placeholder={strings("login.mobile")}
placeholderTextColor="#bbbbbb"
value={formprops.values.mobileNo}
onChangeText={formprops.handleChange("mobileNo")}
onBlur={formprops.handleBlur("mobileNo")}
keyboardType="numeric"
/>
</View>
{formprops.touched.mobileNo && formprops.errors.mobileNo ? (
<View style={styles.errorMessage}>
<AppText styles={styles.errorMessageText}>
{formprops.errors.mobileNo}
</AppText>
</View>
) : null}
<View style={styles.togglebuttoncontainer}>
<View style={styles.toggleTextView}>
<AppText styles={styles.toggleText}>
{strings("login.keep-login")}
</AppText>
</View>
<View style={styles.toggleView}>
<Switch
trackColor={{ false: "#dddddd", true: "#c1d6ee" }}
thumbColor={{ false: "#ffffff", true: "#007aff" }}
ios_backgroundColor="#dddddd"
onValueChange={(value) =>
formprops.setFieldValue("toggle", value)
}
value={formprops.values.toggle}
style={styles.toggle}
/>
</View>
</View>
<SubmitButton
onpress={formprops.handleSubmit}
btext={strings("login.button-text")}
/>
</View>
)}
</Formik>
</View>
);
};
const mapStateToProps = (state) => {
console.log(state);
return {
success: state.signin.success,
};
};
const mapDispatchToProps = (dispatch) => {
return {
sendOTP: (number) => dispatch(signinActions.sendOtpActionCreator(number)),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Login);
But when I try to submit the form and do the action it is giving me this error warning.
Possible Unhandled Promise Rejection (id: 0): Error: Actions must be plain objects. Use custom middleware for async actions.
Can someone help me to correct these files to get rid of this warning? I am very new to Redux-thunk middleware. I tried a lot to find out a solution to this problem but I unable. Thank you
Upvotes: 0
Views: 217
Reputation: 465
@Atyos. I added comment you can have a look.
could you change the code in your action file:
import * as API from './httpClient';
import * as endPoints from './endpoints';
export const SEND_OTP = 'otp/SEND_OTP';
export const SEND_OTP_SUCCESS = 'otp/SEND_OTP_SUCCESS';
export const SEND_OTP_FAILD = 'otp/SEND_OTP_FAILD';
const sendOtpActionCreator = (value) => {
return (dispatch) => {
return API.Post(endPoints.SEND_OTP, {data: value})
.then((data) => {
// it is not correct way to call the dispatch
dispatch(SEND_OTP_SUCCESS, data);
// the dispatch action accept only the plain object
// you should try this code
dispatch({type: SEND_OTP_SUCCESS, payload: data});
})
.catch((err) => {
dispatch(SEND_OTP_FAILD, err);
});
};
};
export default {
sendOtpActionCreator: sendOtpActionCreator,
};
Upvotes: 1