#reactjs #redux #react-redux #axios #redux-thunk
Вопрос:
Я занимаюсь этим уже давно. Я передвигал вещи, как мне кажется, всеми возможными способами. После поиска по переполнению я не смог найти решение из любых других вопросов, заданных другими пользователями.
У меня есть приложение, которое позволяет пользователям входить в систему. Я использую redux для хранения учетных данных пользователя ПОСЛЕ того, как он войдет в систему, чтобы получить свой JWT. Я хочу иметь возможность войти в систему и сразу же увидеть себя вошедшим в систему. Но это происходит только после того, как я войду в систему после обновления браузера.
Итак, в react у меня есть форма входа в систему, которая вызывает функцию ниже после выполнения всех типичных функций сбора информации о пользователе (логин и пароль). Обратите внимание, что мне нужна отправка там, даже если я на самом деле ее не использую, потому что в противном случае я получу сообщение об ошибке «действия должны быть обычными объектами».
В конце этого обещания я звоню getUser, чтобы он взял этот JWT и вернулся с сервера со всей информацией об этой учетной записи. В отладчике он проходит через функцию входа в систему, а затем функцию getUser, но, похоже, никогда не сохраняет ее в redux, если я не обновлю браузер.
export const loginUser = (credentials) => dispatch => {
axios.post('api_call', credentials)
.then(res => {
debugger;
const token = res.data.token;
localStorage.setItem('token', token);
alert("You have logged in successfully!");
getUser(token);
});
}
export const getUser = (token) => dispatch => {
debugger;
axios.get('api_call', {
headers: {"Authorization" : `Bearer ${token}`}
}).then(user => dispatch({
type: GET_USER,
payload: [user.data]
}));
}
Позвольте мне также показать вам мой редуктор:
import { LOGIN_USER, REGISTER_USER, GET_USER, LOGOUT_USER } from "../actions/types";
const initialState = {
items: []
}
export default function(state = initialState, action){
switch(action.type){
case REGISTER_USER:
return{
...state,
items: action.payload
};
// case LOGIN_USER:
// return{
// ...state,
// items: action.payload
// };
case GET_USER:
debugger;
return{
...state,
items: action.payload
};
case LOGOUT_USER:
return{
...state,
items: []
}
default:
return state;
}
}
I have the LOGIN_USER commented out because I realize I’m not actually dispatching anything to the store, rather, just saving JWT to local storage.
Позвольте мне также упомянуть о том, что я пробовал. Я подумал, что, может быть, getUser не может быть вызван так, как я пытался. Поэтому по навигационной ссылке, которая перенаправляет на дом, я попытался поместить туда вызов getUser. Я попытался поместить getUser в крючок useEffect на домашнем компоненте, чтобы имитировать componentDidMount. Я попытался позвонить getUser непосредственно после вызова LoginUser в реальной форме входа. Это не работает из-за асинхронности (к тому времени в локальном хранилище не было jwt). Я попробовал поменять детали своего редуктора.
Вот мой корневой редуктор и хранилище для хорошей меры. Редуктор аутентификации относится ко всем функциям входа в систему, выхода из системы и регистрации.
import { combineReducers } from "redux";
import showReducer from './showReducer';
import gearReducer from './gearReducer';
import authReducer from './authReducer';
import musicReducer from './musicReducer';
import profileReducer from './profileReducer';
import bagReducer from './bagReducer';
export default combineReducers({
shows: showReducer,
gear: gearReducer,
auth: authReducer,
music: musicReducer,
profile: profileReducer,
bag: bagReducer
});
import { createStore, applyMiddleware, compose } from "redux";
import thunk from 'redux-thunk';
import rootReducer from './reducers/rootReducer';
import { composeWithDevTools } from 'redux-devtools-extension';
//initial app state
const initialState = {};
//middleware
const middleware = [thunk];
//...middleware (spread operator) because we want it to be added on to the middleware array
const store = createStore(
rootReducer,
initialState,
composeWithDevTools(
applyMiddleware(...middleware)
)
);
export default store;
Позвольте мне также упомянуть, что когда я обновляю страницу, отладчик выполняет функцию componentDidMount для основного приложения, которое декодирует jwt и вызывает getUser.
Я считаю, что это весь соответствующий код, но я могу обновить его при необходимости. Заранее благодарю вас и прошу прощения за дрянной вопрос.
Ответ №1:
Из того, что я вижу, вы не отправляете свои getUser
действия в магазин.
Даже если вы выполняете другие действия, вам все равно нужно отправлять действия в свой магазин redux, если вы хотите, чтобы они были обработаны. getUser
сама по себе это просто функция создания действия, а в данном случае-асинхронный создатель действия, который возвращает функцию, которую все еще необходимо отправить в хранилище.
export const loginUser = (credentials) => dispatch => {
axios.post('api_call', credentials)
.then(res => {
const token = res.data.token;
localStorage.setItem('token', token);
alert("You have logged in successfully!");
dispatch(getUser(token)); // <-- dispatch getUser action!
});
}
Комментарии:
1. Да! Я должен был воспринять полученное исключение как намек. Ну что ж, по крайней мере, я больше никогда не совершу этой ошибки, и теперь я немного больше понимаю redux. Спасибо!