Redux即使在返回新的状态对象后也不更新组件



我是redux新手。我要做的是从redux获取认证状态state和相应地渲染组件如果auth为真,则渲染home else login,但每次redux返回undefined作为auth状态.

这是我的组件

import axios from 'axios';
import jsonwebtoken from 'jsonwebtoken';
import Login from './Containers/Login'
import Home from './Containers/Home'
import {connect } from 'react-redux'
const server = 'http://localhost:5000/api/';
function getCookie(cname) {
let name = cname + "=";
let ca = document.cookie.split(';');
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) === ' ') {
c = c.substring(1);
}
if (c.indexOf(name) === 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
function App({auth, setstate}) {
useEffect(()=>{
const fetchdata = async ()=>{
const token = getCookie('token');
let loggedInUser = {};
if (token !== '') {
try {
loggedInUser = await jsonwebtoken.verify(token, 'shhhhh')._doc;
const res1 = await axios.post(server + 'userlist/getlist', { id: loggedInUser._id });
const res2 = await axios.post(server + 'usertodo/gettodo', { listid: loggedInUser.defaultListid });
if (res1.data.error === null && res2.data.error === null) {
const { lists } = res1.data;
const { todos } = res2.data;
const newState = {
isAuth: true,
loggedInUser,
selectedListid: loggedInUser.defaultListid,
todos,
lists
}
setstate(newState)
}
else{
console.log(res1.data.error, res2.data.error);
setstate({
isAuth:false
})
}
} catch (err) {
console.log(err)
}
}
}
fetchdata();
},[setstate, auth])
return (auth ? <Home/>:<Login/>);
}
const mapStateToProps = state =>{
return {
auth: state.isAuth
}
}
const mapDispatchToProps = dispatch =>{
return {
setstate: async(newState)=> dispatch({type:'SET_STATES', newState})
}
}
export default connect(mapStateToProps, mapDispatchToProps)(App);

=========================================================================

this is my initialState

isAuth: false,
loggedInUser: null,
selectedListid: null,
todos: [],
lists: []
}

和减速机

switch (action.type) {
case 'SET_STATES':
{
const { newState } = action
return {
...state,
...newState
}
}
default:
return state;

我建议你使用thunk而不是在你的组件中使用所有的异步逻辑,而不是使用connect,你可以使用react-redux中的useSelector和useDispatch钩子。您还应该创建操作创建器函数并将操作类型存储在常量中。只使用SET_STATE操作来设置整个状态会违背redux的目的,请尝试创建执行特定任务的操作。

我没有得到未定义为使用您的确切代码的认证状态,所以你的问题中一定有缺失的东西。您是否尝试检查redux devtools,您是否可以向我们提供那里的信息,如什么是状态,什么动作被派遣,他们对状态做了什么更改?fetch代码也可能有问题,所以它最终会在catch中结束,但之后什么也不会发生,你的auth不应该是undefined,因为它是在初始状态设置的。

如果你仍然无法让你的代码正常工作,那么我建议在你的问题中添加一个可运行的代码片段,以再现问题或创建一个沙箱

下面是您的redux代码按预期工作,我添加了一个额外的检查,如果auth为false,那么当您已经通过身份验证时,它将不会进行身份验证:

const { Provider, connect } = ReactRedux;
const { createStore, applyMiddleware, compose } = Redux;
const initialState = {
isAuth: false,
};
const reducer = (state, action) => {
switch (action.type) {
case 'SET_STATES': {
const { newState } = action;
return {
...state,
...newState,
};
}
default:
return state;
}
};
//creating store with redux dev tools
const composeEnhancers =
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
reducer,
initialState,
composeEnhancers(
applyMiddleware(
() => (next) => (action) => next(action)
)
)
);
//fake getCookie
const getCookie = () => 'token';
function App({ auth, setstate }) {
React.useEffect(() => {
//removed async because SO has ancient babel
const fetchdata = () => {
const token = getCookie('token');
if (token !== '' && auth === false) {
//only do this if not authenticated
const newState = {
isAuth: true,
};
setstate(newState);
}
};
fetchdata();
}, [setstate, auth]);
return <div>auth is: {String(auth)}</div>;
}
const mapStateToProps = (state) => {
return {
auth: state.isAuth,
};
};
const mapDispatchToProps = (dispatch) => {
return {
//removed async because SO as ancient babel
setstate: (newState) =>
dispatch({ type: 'SET_STATES', newState }),
};
};
const ConnectedApp = connect(
mapStateToProps,
mapDispatchToProps
)(App);
ReactDOM.render(
<Provider store={store}>
<ConnectedApp />
</Provider>,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script>

<div id="root"></div>

最新更新