请求代码:
export class LogInContainer extends Component {
submit = (values) => {
const { mutate } = this.props;
mutate({
variables: {
email: values.email,
password: values.password,
},
})
.then((res) => {
const token = res.data.login.token;
localStorage.setItem("token", token);
const user = res.data.login.user;
const { logIn } = this.props;
logIn(user);
this.props.history.push("/pages/processes");
})
.catch((error) => {
const errorMessage = error.message;
const { logInError } = this.props;
logInError(errorMessage);
});
};
render() {
const { error, logInCleanError } = this.props;
return (
<LogIn
onSubmit={this.submit}
errorMessage={error}
logInCleanError={logInCleanError}
/>
);
}
}
export default compose(
graphql(LOG_IN),
withRouter,
connect(({ errors }) => ({ error: errors.log_in_error }), {
logInError,
logInCleanError,
logIn,
})
)(LogInContainer);
减速器代码:
const initialState = {
user: {
id: "",
firstName: "",
secondName: "",
email: "",
isAuth: localStorage.getItem('token') ? true : false,
},
};
export const userReducer = (state = initialState, { type, user }) => {
switch (type) {
case LOG_IN:
return {
...state,
user: {
id: user.id,
firstName: user.firstName,
secondName: user.secondName,
email: user.email,
isAuth: true,
},
};
case CURRENT_USER:
return {
...state,
user: {
id: user.id,
firstName: user.firstName,
secondName: user.secondName,
email: user.email,
isAuth: true,
},
};
case LOG_OUT:
return {
...state,
user: {
id: "",
firstName: "",
secondName: "",
email: "",
isAuth: false,
},
};
default:
return state;
}
};
我保存JWT并将其放在每个请求的标头中,例如:
const client = new ApolloClient({
uri: "http://localhost:4000/api",
request: (operation) => {
const token = localStorage.getItem("token");
operation.setContext({
headers: {
authorization: token ? `Bearer ${token}` : "",
},
});
},
});
我可以像这样保护路由器:
const App = ({ authorized }) => {
return (
<Switch>
{!authorized ? (
<Route path="/auth">
<Auth />
</Route>
) : (
<Route path="/pages">
<Pages />
</Route>
)}
<Redirect from="/" to="/auth/login" />
</Switch>
);
};
export default App;
刷新登录页面后,我不会丢失JWT并留在系统中,但是会丢失用户名,第二名等的redux状态,需要在页面上显示该状态。那么,在这种情况下,如果没有类似redux-persist之类的插件
,保存redux状态的正确方法是什么?答案 0 :(得分:1)
作为Dan Abramov suggests,您应该在local storage
方法中使用store's subscribe
:
store.subscribe(() => {
// persist your state
})
在创建商店之前,请阅读以下保留的部分:
const persistedState = // ...
const store = createStore(reducer, persistedState)
如果使用
combineReducers()
,您会发现减速器没有 接收到的状态将使用其默认的state
正常“启动” 参数值。这可能非常方便。建议您对订户进行反跳操作,以便不要写 到localStorage的速度太快,否则您会遇到性能问题。
最后,您可以创建一个中间件,将其封装为 另一种选择,但我将从订户开始,因为它更简单 解决方案,并且做得很好。
答案 1 :(得分:0)
使用localStorage:
localStorage.setItem('token', token);
并在应用程序加载时检查是否设置了令牌,如果已设置,则从localStorage获取信息
localStorage.getItem('token');
您还可以保存用户信息:
localStorage.setItem('user', JSON.stringify(userInfo));
并使用JSON.parse获取它。
答案 2 :(得分:0)
答案 3 :(得分:0)
?不久
做到这一点:
const initialState = {
user: {
id: localStorage.getItem('id') || '',
firstName: localStorage.getItem('firstName') || '',
secondName: localStorage.getItem('secondName') || '',
email: localStorage.getItem('email') || '',
isAuth: localStorage.getItem('token') ? true : false,
},
}
?有点复杂但可扩展的方式
创建一个middleware,它将服务与应用程序持久状态相关的所有内容。您可以在那里将数据保存到localStorage,cookie或IndexedDB。中间件,我们称它为LocalStoreMiddleware,它将监听您的redux reducer所做的相同操作,无论每个中间件在何处以及由谁(组件,Saga,Socket)分派操作,何时分发操作,reduce都会更新redux存储, LocalStoreMiddleware会将数据保存到localStorage,cookie,indexDB等。
优势
创建一个文件,您将在其中存储与持久数据相关的功能
// local-store-resolvers.js
import {on} from './local-store-middleware.js'
function saveToken(action, state) {
localStorage.setItem('token', JSON.stringify(state.token));
}
function saveUsername(action) {
localStorage.setItem('username', JSON.stringify(action.username));
}
export default [
on(AUTHORIZATION, saveToken),
on(USERNAME_CHANGED, saveUsername),
]
中间件工厂
// local-store-middleware.js
export const on = (actionType, resolver) => (action, state) => (
actionType === action.type && resolver(action, state)
)
const createLocalStoreMiddleware = resolvers => store => next => action => {
resolvers.forEach(
resolver => resolver(action, store.getState())
)
return next(action)
}
export default createLocalStoreMiddleware
Redux商店
// src/store/index.js - your main file where you create redux store
import createLocalStoreMiddleware from './local-store-middleware.js'
import resolvers from './local-store-resolvers.js'
const localStore = createLocalStoreMiddleware(resolvers)
const store = createStore(
combineReducers({users, someOtherReducer}),
applyMiddleware(localStore), // if you have more middlewares use compose
)
export default store