I got an error when user authReduce. When log this reducer and it show "underfine"
I'm using:
Redux persist store auth state
Redux toolkit
Sometime I try hot reload it work. So I don't understand why?
The problem appears when I store reducer and actions in the same file (In one file have too many exports) so I resolved this problem by the way split reducer(authReducer.js) and actions(authSlice.js) are two files like this:
// authReducer.js
import { createSlice } from '#reduxjs/toolkit';
export const authSlice = createSlice({
name: 'auth',
initialState: {
isLoading: true,
userToken: null,
isUserGuest: true,
isJailBroken: false,
isSubscription: true,
isShowCheckPassCode: false,
passCodeMessage: 'Đây là phiên bản nội bộ, Vui lòng nhập pass để sử dụng.',
passCode: '',
isShowPopupPassword: false,
userEmail:'',
typeLogin:'',
isShowLoginGGFB:true
},
reducers: {
signIn: {
reducer(state, action) {
const { token } = action.payload;
state.userToken = token
state.isLoading = false
},
prepare(token, userInfo) {
return { payload: { token, userInfo } }
}
},
skipAuth(state, action) {
state.isUserGuest = true;
state.userToken = null;
},
signout(state, action) {
state.userToken = null
state.isUserGuest = false;
},
setIsJailBroken(state, action) {
state.isJailBroken = true
},
setSubscriptionNoti(state, action) {
state.isSubscription = action.payload
},
setIsShowCheckPassCode(state, action) {
state.isShowCheckPassCode = action.payload
},
setDataPasscode(state, action) {
state.isShowCheckPassCode = action.payload.isShowCheckPassCode
state.passCodeMessage = action.payload.passCodeMessage
state.passCode = action.payload.passCode
},
setShowLoginGGFB(state, action){
state.isShowLoginGGFB = action.payload
},
setActivePopupPassword(state, action) {
state.isShowPopupPassword = action.payload
},
setUserEmail(state,action){
state.userEmail = action.payload
},
setTypeLogin(state,action){
state.typeLogin = action.payload
}
}
})
export const authReducer = authSlice.reducer
// authSlice.js
export const {
signIn,
signout,
restore,
skipAuth,
setIsJailBroken,
setSubscriptionNoti,
setIsShowCheckPassCode,
setDataPasscode,
setActivePopupPassword,
setUserEmail,
setTypeLogin,
setShowLoginGGFB,
} = authSlice.actions;
export const callActionSignOut = (isForce = true) => async dispatch => {
try {
if (isForce) {
await signOut();
}
dispatch(signout());
dispatch(
setFavorite({
dataFavorite: [],
objectDataFavorite: {},
}),
);
dispatch(fetchCartSuccess(null));
dispatch(resetUserInternal());
dispatch(clearUser());
} catch (error) {
console.log('callActionSignOut -> error', error);
}
};
Related
I currently started learning redux. My code was working perfectly with core redux, then I tried out #reduxjs/toolkit and now I'm unable to access the function to change the state in the store. Here is my code of reducer.
const seasonEdits = createSlice({
name: "seasons",
initialState: [],
reducers: {
addSeason(state, action) {
state.push(action.payload);
console.log("this here");
},
removeSeason(state, action) {
state.filter((season) => season.id !== action.payload);
},
markComplete(state, action) {
state.map((season) => {
if (season.id == action.payload) season.isWatched = !season.isWatched;
});
},
},
});
export const { addSeason, removeSeason, markComplete } = seasonEdits.actions;
export default seasonEdits.reducer;
and my store.js file
import { configureStore } from "#reduxjs/toolkit";
import seasonReducer from "./reducer";
export default store = configureStore({
reducer: {
seasons: seasonReducer,
},
});
and the add.js file which has add functionality. Calling a handleSubmit function which is creating an object and adding it to an array which is the state in store.
const handleSubmit = async () => {
try {
if (!name || !totalNoSeason) {
return alert("Please add both fields");
}
const seasonToAdd = {
id: shortid.generate(),
name,
totalNoSeason,
isWatched: false,
};
addSeason(seasonToAdd);
navigation.navigate("Home");
} catch (error) {
console.log(error);
}
};
const mapDispatchToProps = (dispatch) => {
return {
addSeason: (data) => dispatch(addSeason(data)),
};
};
Add.propTypes = {
addSeason: propTypes.func.isRequired,
};
export default connect(null, mapDispatchToProps)(Add);
The issue is that array.map() and array.filter() return new arrays! Right now your reducers are calling those functions, and then just throwing away the new arrays:
removeSeason(state, action) {
// The return value is thrown away and ignored!
state.filter((season) => season.id !== action.payload);
},
You need to return the new value:
removeSeason(state, action) {
// Now RTK will see the new return value
return state.filter((season) => season.id !== action.payload);
},
See https://redux-toolkit.js.org/usage/immer-reducers#resetting-and-replacing-state for more details.
I have a simple question. I am implementing the useSelector Hook React Native together with ReduxToolKit.
But now the problem when the useSelector have data or not empty and everytime I change my screen the useSelector data remain the same data.
I want when change screen my useSelector data to be empty array again.
How do I solve this problem ?
Thank You
EDIT :
ApiChartingSlice.js
export const ApiChartingDataThunk = createAsyncThunk(
'ApiChartingData',
async (data) => {
try {
const {chart, ticker} = data;
const response = await ApiChartingData(chart, ticker);
return response;
} catch (error) {
return console.log({ error: error.message });
}
}
)
// status: 'idle' | 'loading' | 'succeeded' | 'failed',
export const ApiChartingDataSlice = createSlice({
name: 'ApiChartingData',
initialState: {
apiData: [],
status: 'idle',
error: null
},
reducers: {},
extraReducers: {
[ApiChartingDataThunk.pending.type]: (state, action) => {
state.playerList = {
status: state.status = 'loading',
apiData: [],
error: {},
};
},
[ApiChartingDataThunk.fulfilled.type]: (state, action) => {
state.playerList = {
status: state.status = 'idle',
apiData: state.apiData = action.payload,
error: {},
};
},
[ApiChartingDataThunk.rejected.type]: (state, action) => {
state.playerList = {
status: state.status = 'failed',
apiData: [],
error: action.payload,
};
},
}
});
ChartUserCard.js
const tickerData = useSelector(state => state.ApiTicker.apiData);
const checkTicker = useCallback(() => {
dispatch(ApiTickerThunk(inputValue))
.unwrap()
.then((originalPromiseResult) => {
// console.log(originalPromiseResult);
})
.catch((rejectedValueOrSerializedError) => {
console.log(rejectedValueOrSerializedError);
});
setStart(true);
}, [dispatch, inputValue, tickerData]);
in Here : const tickerData = useSelector(state => state.ApiTicker.apiData);
I want to reset tickerData.
Thank To #this.arjun.
const dataThunk = {chart: "", ticker: ""};
const tickerThunk = "";
const resetDataThunk = useCallback(() => {
dispatch(ApiTickerThunk(tickerThunk));
dispatch(ApiChartingDataThunk(dataThunk));
}, [dispatch]);
Just use dispatch empty data.
I have a problem calling the action from vuex. Everytime I try to access the loginUser action I get an error 'unknown action type' from vuex. maybe I'm not calling it the right way. Please tell me what's wrong with my code.
store: user.js
import axios from 'axios'
export const state = () => ({
users: [],
loggedIn: false,
})
export const getters = {
getLoggedIn: (state) => { return state.loggedIn },
}
export const actions = {
loginUser({ commit }, payload){
if(state.loggedIn){
console.log("you're already logged in!")
}else{
return new Promise(async(resolve, reject) => {
const { data } = await axios.post('/api/users/login-admin', {
login: payload.login,
password: payload.password
})
if(data.success){
commit("loggedIn", true)
resolve()
}else{
commit("loggedIn", false)
reject('an error has ocurred')
}
return data.success
}).catch(err => alert(errCodes(err.code)))
}
},
}
export const mutations = {
setLoggedIn(state, payload) {
state.loggedIn = payload
}
}
login.vue
computed: {
...mapGetters(['getCount'] , {user: 'getLoggedIn'}),
...mapActions([
'loginUser'
]),
},
methods: {
onSubmit: function(){
this.$store.dispatch({
type: 'loginUser',
email: this.login,
pass: this.pass
}).then(()=>{
this.$router.push('../admin_2065')
this.onReset()
}).catch(e => console.log(e))
},
onReset(){
this.login = ''
this.pass = ''
this.$nextTick().then(() => {
this.ready = true
})
}
},
error:
any help will be appreciated, thanks.
mapActions should be inside the methods option and add the namespace user/ :
computed: {
...mapGetters(['getCount'] , {user: 'getLoggedIn'}),
},
methods: {
...mapActions([
'user/loginUser'
]),
onSubmit: function(){
this['user/loginUser']({
email: this.login,
pass: this.pass
}).then(()=>{
this.$router.push('../admin_2065')
this.onReset()
}).catch(e => console.log(e))
},
onReset(){
this.login = ''
this.pass = ''
this.$nextTick().then(() => {
this.ready = true
})
}
},
I'm starting on React-Native, (and sorry for my English too).
After several researches, I cannot find the solution of this problem.
And I can't really understand this problem.
import { connect } from 'react-redux';
import ListComics from '../components/ListComics';
import { fetchPostscomics } from "../action/comics";
const mapStateToProps = state => {
return {
comics: state.postcomics.postscomics,
//loading: state.postcomics.loading
};
};
const mapDispatchToProps = dispatch => {
return {
fetchPostscomics: () => dispatch(fetchPostscomics()),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(ListComics);
reducer:
``
import {
FETCH_POSTSCOMICS_REQUEST,
FETCH_POSTSCOMICS_SUCCESS,
FETCH_POSTSCOMICS_FAILURE
} from '../action/comics';
import {
ADD_POSTCOMICS_REQUEST,
ADD_POSTCOMICS_SUCCESS,
ADD_POSTCOMICS_FAILURE,
} from '../action/addComics';
const initialState = {
comics: []
};
function postcomics(state = initialState, action) {
switch(action.type) {
case FETCH_POSTSCOMICS_REQUEST:
return { ...state, loading: true };
case ADD_POSTCOMICS_REQUEST:
return { ...state, loading: true };
case FETCH_POSTSCOMICS_SUCCESS:
return {
...state,
comics: action.payload,
loading: false
};
case ADD_POSTCOMICS_SUCCESS:
return { comics: [...state.postscomics, action.payload]};
case FETCH_POSTSCOMICS_FAILURE:
return { ...state, error: action.payload, loading: false };
case ADD_POSTCOMICS_FAILURE:
return { ...state, error: action.payload, loading: false };
default:
return state;
}
}
const store = combineReducers({postcomics});
export default createStore(store, applyMiddleware(thunk));
``
`Code FectchPostscomics:
export const FETCH_POSTSCOMICS_REQUEST = 'FETCH_POSTSCOMICS_REQUEST';
export const FETCH_POSTSCOMICS_SUCCESS = 'FETCH_POSTSCOMICS_SUCCESS';
export const FETCH_POSTSCOMICS_FAILURE = 'FETCH_POSTSCOMICS_FAILURE';
export function fetchPostscomics() {
return function (dispatch) {
dispatch(fetchPostscomicsRequest());
console.log(process.env.API_URL);
return fetch('http://192.168.1.23:4000/comics')
.then(
response => response.json(),
error => dispatch(fetchPostscomicsFailure(error))
)
.then(postscomics => {
dispatch(fetchPostscomicsSuccess(postscomics));
});
}
}
export function fetchPostscomicsRequest() {
return {type: FETCH_POSTSCOMICS_REQUEST};
}
export function fetchPostscomicsSuccess(posts) {
return {type: FETCH_POSTSCOMICS_SUCCESS, payload: { comics: postscomics} };
}
export function fetchPostscomicsFailure(error) {
return {type: FETCH_POSTSCOMICS_FAILURE, payload: error};
}
Youy action.payload is an object ... and you need to pass only comics to your state ... not the whole object
case FETCH_POSTSCOMICS_SUCCESS:
return {
...state,
...action.payload,
loading: false
};
OR
case FETCH_POSTSCOMICS_SUCCESS:
return {
...state,
comics: action.payload.comics,
loading: false
};
And regarding accessing your comics state:
const mapStateToProps = state => {
return {
comics: state.postcomics.comics // <-- Look at this
};
};
Same thing for other actions like ADD_POSTCOMICS
I am moving from classes to hooks in react native but facing some issues using redux with hooks.
My work till now
Login.js
const Login = props => {
const {navigation} = props;
const dispatch = useDispatch();
const {success, loading, error} = useSelector(state => state.auth);
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const onLoginPress = async () => {
await dispatch(login(email, password)); //here VSCode give hints await is useless ? Why ? how to use await then ?
if (success) {
navigation.navigate('Home');
} else {
alert(error || 'Invalid Credentials. Please Try again');
}
};
//other code
export default Login;
I am dispatching login action when user presses login button. But problem is app stucks here and action doesn't complete and always remains auth_loading
my login action
export const login = (email, pass) => {
return async dispatch => {
dispatch(authLoading());
try {
const res = await firebaseService
.auth()
.signInWithEmailAndPassword(email, pass); //here app action stucks
dispatch(loginSuccess(res));
} catch (err) {
dispatch(authFailed(err.message));
}
};
};
My reducer
import {
LOGIN_EMAIL_CHANGED,
LOGIN_PASS_CHANGED,
LOGIN_SUCCESS,
REGISER_SUCCESS,
} from '../types';
import {AUTH_FAILED, AUTH_LOADING} from '../actions/AuthActions';
const initialState = {
loginEmail: null,
loginPass: null,
loading: false,
success: false,
user: null,
error: '',
authenticated: false,
};
export const AuthReducer = (state = initialState, action) => {
switch (action.type) {
case LOGIN_EMAIL_CHANGED:
return {
...state,
loginEmail: action.payload,
};
case LOGIN_PASS_CHANGED:
return {
...state,
loginPass: action.payload,
};
case AUTH_LOADING: {
return {
...state,
success: false,
loading: true,
error: '',
};
}
case AUTH_FAILED: {
return {
...state,
loading: false,
success: false,
error: action.payload,
};
}
case LOGIN_SUCCESS: {
return {
...state,
user: action.payload,
loading: false,
success: true,
error: null,
};
}
case REGISER_SUCCESS: {
return {
...state,
user: action.payload,
loading: false,
success: true,
error: null,
};
}
default:
return state;
}
};
Am i using hooks in right way ?
Or how to await after dispatching action in hook. ?
Help will be appreciated.
Thanks