【问题标题】:Redux is not updating component even after returning new state object即使返回新的状态对象,Redux 也不会更新组件
【发布时间】:2021-08-12 09:04:50
【问题描述】:

我是 redux 的新手。 我要做的是从redux状态获取身份验证状态,如果身份验证为真,相应地渲染我的组件然后渲染主页否则登录,但每次 redux 是返回未定义为身份验证状态

这是我的组件

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);

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

这是我的初始状态

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

和减速器

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

【问题讨论】:

    标签: javascript reactjs redux react-redux react-state-management


    【解决方案1】:

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

    我没有使用您的确切代码将未定义为身份验证状态,因此您的问题中一定缺少某些内容。您是否尝试检查 redux 开发工具,您能否向我们提供信息,例如状态是什么、调度了哪些操作、它们对状态做了哪些更改?提取代码也可能有问题,因此它最终会被捕获,但不会发生任何事情,并且您的身份验证不应该是未定义的,因为它设置为初始状态。

    如果您仍然无法让代码正常工作,那么我建议在您的问题中添加runnable snippet 以重现问题或创建sandbox

    以下是您的 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>

    【讨论】:

      猜你喜欢
      • 2021-01-12
      • 2021-04-09
      • 1970-01-01
      • 2021-07-26
      • 2021-11-07
      • 1970-01-01
      • 2019-05-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多