在 ReactJS + Redux 中同时从 LocalStorage 写入然后读取
Write and then read at the same time from LocalStorage in ReactJS + Redux
我正在尝试写入 localStorage,然后从 localStorage 身份验证令牌中读取以访问 API。
export const authLogin = (username, password) => {
return (dispatch) => {
dispatch(authStart());
axios
.post(" http://localhost:8000/rest-auth/login/", {
username: username,
password: password,
})
.then((res) => {
const token = res.data.key;
const expirationDate = new Date(new Date().getTime() + 3600 * 1000);
try {
localStorage.setItem("token", token);
localStorage.setItem("expirationDate", expirationDate);
dispatch(authSuccess(token));
dispatch(checkAuthTimeout(3600));
} catch (error) {
console.log("error storing data");
}
})
.catch((err) => {
dispatch(authFail(err));
});
};
};
然后从我想从 localStorage 中读取的 ReactJS 方法:
import axios from "axios";
import { endpoint } from "./constants";
var token = localStorage.getItem("token");
export const authAxios = axios.create({
baseURL: endpoint,
headers: {
Authorization: `Token ${token ? localStorage.getItem("token") : null}`,
},
});
class OrderSummary extends React.Component {
_isMounted = false;
state = {
data: null,
error: null,
loading: false,
};
componentDidMount() {
this._isMounted = true;
this.handelFetchOrder();
}
componentWillUnmount() {
this._isMounted = false;
}
handelFetchOrder = () => {
this.setState({ loading: true });
authAxios
.get(orderSummaryURL)
.then((res) => {
this.setState({ data: res.data, loading: false });
console.log(res.data);
})
.catch((err) => {
if (err.response.status === 404) {
this.setState({
error: "You currently do not have any order",
loading: false,
});
} else {
this.setState({ error: err, loading: false });
}
});
};
我的问题是当我从 localStorage 读取 时。如果令牌变为空。这会导致 401 api 代码,因为我们无法读取令牌以将其传递给 api 以获得结果。但是,如果我刷新网络浏览器 (F5),则一切正常。
在您的示例中,您在加载文件时为 axios 设置令牌。这意味着只有在应用程序加载时,而不是在您登录后。因此 localStorage
中的项目当时为空。
所以解决方案是为 axios 设置拦截器而不是 authAxios
:
const App = (props) => {
// This will trigger when only once when page refreshes
useEffect(() => {
axios.interceptors.request.use(
(config) => {
config.headers = {
...config.headers,
Authorization: `Token ${token ? localStorage.getItem("token") : null}`
};
return config;
},
(error) => {
props.dispatchRedirectToLoginPage()
return Promise.reject(error);
}
);
}, [])
return <div>Your app</div>
}
这样每个请求都会执行这个函数,并且会从localStorage中获取token。
您使用 axios.get(...)
或您需要的任何方法进行的每个 api 调用。
我正在尝试写入 localStorage,然后从 localStorage 身份验证令牌中读取以访问 API。
export const authLogin = (username, password) => {
return (dispatch) => {
dispatch(authStart());
axios
.post(" http://localhost:8000/rest-auth/login/", {
username: username,
password: password,
})
.then((res) => {
const token = res.data.key;
const expirationDate = new Date(new Date().getTime() + 3600 * 1000);
try {
localStorage.setItem("token", token);
localStorage.setItem("expirationDate", expirationDate);
dispatch(authSuccess(token));
dispatch(checkAuthTimeout(3600));
} catch (error) {
console.log("error storing data");
}
})
.catch((err) => {
dispatch(authFail(err));
});
};
};
然后从我想从 localStorage 中读取的 ReactJS 方法:
import axios from "axios";
import { endpoint } from "./constants";
var token = localStorage.getItem("token");
export const authAxios = axios.create({
baseURL: endpoint,
headers: {
Authorization: `Token ${token ? localStorage.getItem("token") : null}`,
},
});
class OrderSummary extends React.Component {
_isMounted = false;
state = {
data: null,
error: null,
loading: false,
};
componentDidMount() {
this._isMounted = true;
this.handelFetchOrder();
}
componentWillUnmount() {
this._isMounted = false;
}
handelFetchOrder = () => {
this.setState({ loading: true });
authAxios
.get(orderSummaryURL)
.then((res) => {
this.setState({ data: res.data, loading: false });
console.log(res.data);
})
.catch((err) => {
if (err.response.status === 404) {
this.setState({
error: "You currently do not have any order",
loading: false,
});
} else {
this.setState({ error: err, loading: false });
}
});
};
我的问题是当我从 localStorage 读取 时。如果令牌变为空。这会导致 401 api 代码,因为我们无法读取令牌以将其传递给 api 以获得结果。但是,如果我刷新网络浏览器 (F5),则一切正常。
在您的示例中,您在加载文件时为 axios 设置令牌。这意味着只有在应用程序加载时,而不是在您登录后。因此 localStorage
中的项目当时为空。
所以解决方案是为 axios 设置拦截器而不是 authAxios
:
const App = (props) => {
// This will trigger when only once when page refreshes
useEffect(() => {
axios.interceptors.request.use(
(config) => {
config.headers = {
...config.headers,
Authorization: `Token ${token ? localStorage.getItem("token") : null}`
};
return config;
},
(error) => {
props.dispatchRedirectToLoginPage()
return Promise.reject(error);
}
);
}, [])
return <div>Your app</div>
}
这样每个请求都会执行这个函数,并且会从localStorage中获取token。
您使用 axios.get(...)
或您需要的任何方法进行的每个 api 调用。