redux存储中的更改不会在使用该状态的任何位置执行重新渲染



我正试图从spotify提供的api中获取令牌,这里的一切都按预期工作,只有一个除外。当我的reducer更新我的身份验证状态时,它不会在使用过任何身份验证令牌的组件中执行重新呈现。更新商店后,它仍然显示未定义,但当我刷新登录url时,它显示了以前所做的更改。

这是我的登录名。jsx

import { generateAuthorizeUrl, extractUrlParams } from "../utils";
import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { scopes } from "../spotify";
import { signIn } from "../actions";
const Login = (props) => {
const { refreshToken, loading, error } = useSelector((state) => state.auth);
console.log(refreshToken, loading, error);
const dispatch = useDispatch();
const onClickHandler = function (e) {
e.preventDefault();
var a = document.createElement("a");
a.href = generateAuthorizeUrl()(scopes);
a.click();
};
useEffect(() => {
if (window.location.search.includes("code=") && !refreshToken) {
var { code, state } = extractUrlParams();
dispatch(signIn(code, state));
}
}, [dispatch, refreshToken]);
return (
<div>
{props.refreshToken}
<button onClick={onClickHandler}>login with spotify</button>
</div>
);
};
export default Login;

以下是当spotify在url 中使用代码和状态参数重定向我时要执行的authAction

import axios from "axios";
import {
USER_SIGNIN_FAILURE,
USER_SIGNIN_REQUEST,
USER_SIGNIN_SUCCESS,
} from "../contants/AuthConstants";
import { Base64, getItem } from "../utils";
// DISPATCH DATA FOR MAKING REQUEST STATE
const signInRequest = () => ({ type: USER_SIGNIN_REQUEST });
// DISPATCH DATA FOR SUCCESS AND FAILURE REQUEST
const signInResponse = (error = false, data) => ({
type: error ? USER_SIGNIN_FAILURE : USER_SIGNIN_SUCCESS,
payload: data,
});
// SIGN IN ACTION TO BE DISPATCHED TO REDUCER FOR LOGIN STUFF
export const signIn = (code, state) => async (dispatch, getState) => {
dispatch(signInRequest());
let _state = getItem(process.env.REACT_APP_STATE_KEY);
//   CHECK IF STATE IS NULL OR PROVIDED STATE DOES NOT MATCHES STATE STORED IN LOCALSTORAGE
if (!state || state !== _state) {
// IF TRUE OUR AUTHORAIZATION FAILS
dispatch(signInResponse(true, "state mismatched, Authorization failed"));
} else {
// ELSE MAKE REQUEST TO TOKEN URI FOR ACCEPTION TOKEN
await axios({
url: process.env.REACT_APP_TOKEN_URI,
method: "POST",
data: new URLSearchParams({
code: code,
redirect_uri: process.env.REACT_APP_REDIRECT_URI,
grant_type: "authorization_code",
}).toString(),
headers: {
Authorization: `Basic ${Base64.encode(
`${process.env.REACT_APP_CLIENT_ID}:${process.env.REACT_APP_CLIENT_SECRET}`
)}`,
"Content-Type": "application/x-www-form-urlencoded",
},
})
.then((res) => {
dispatch(signInResponse(false, res.data));
})
.catch((error) => dispatch(signInResponse(true, error.message)));
}
};

这是authReducer

import {
USER_SIGNIN_FAILURE,
USER_SIGNIN_REQUEST,
USER_SIGNIN_SUCCESS,
} from "../contants/AuthConstants";
import { setItem } from "../utils";
const AuthReducer = (state = { loading: false, error: "" }, action) => {
switch (action.type) {
case USER_SIGNIN_REQUEST:
return { ...state, loading: true };
case USER_SIGNIN_SUCCESS:
let auth = {
refreshToken: action.payload.refresh_token,
accessToken: action.payload.access_token,
expiresIn: new Date().getTime() + 3540 * 1000,
tokenType: action.payload.token_type,
};
setItem(process.env.REACT_APP_TOKEN_KEY)(JSON.stringify(auth));
return {
...state,
loading: false,
auth: auth,
error: null,
};
case USER_SIGNIN_FAILURE:
return { ...state, loading: false, error: action.payload, auth: {} };
default:
return state;
}
};
export { AuthReducer };

这是store.js

import { applyMiddleware, combineReducers, compose, createStore } from "redux";
import thunk from "redux-thunk";
import { AuthReducer } from "../reducers/AuthReducers";
import { getItem } from "../utils";
const initialState = {
auth: getItem(process.env.REACT_APP_TOKEN_KEY)
? JSON.parse(getItem(process.env.REACT_APP_TOKEN_KEY))
: {},
};
const rootReducer = combineReducers({
auth: AuthReducer,
});
const composeEnhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
rootReducer,
initialState,
composeEnhancer(applyMiddleware(thunk))
);
export default store;

这是登录组件父容器

import { BrowserRouter, Routes, Route } from "react-router-dom";
import styled from "styled-components";
import Privateroute from "./route/PrivateRoute";
import { Home, Login } from "./screens";
function App() {
return (
<BrowserRouter>
<AppContainer>
<Routes>
<Route path="/auth/login" element={<Login />} />
<Route
path="/"
element={
<Privateroute>
<Home />
</Privateroute>
}
></Route>
</Routes>
</AppContainer>
</BrowserRouter>
);
}
const AppContainer = styled.div``;
export default App;

最后是我的专用路由组件

import React from "react";
import { useSelector } from "react-redux";
import { Navigate } from "react-router-dom";
const Privateroute = (props) => {
const token = useSelector((state) => state.auth.refreshToken);
return token ? props.children : <Navigate to="/auth/login" />;
};
export default Privateroute;

您需要用<Provider store={store}></Provider>包装代码

最新更新