【问题标题】:Redux/React: Cannot read property 'type' of undefined when changing activePageRedux/React:更改 activePage 时无法读取未定义的属性“类型”
【发布时间】:2021-07-13 05:49:52
【问题描述】:

嘿,这是我第一次在项目中使用 react/redux,所以我一直在将我的“导航”迁移到 redux 风格的实现,我(从这里开始)想要更改商店状态(activePage)单击一个按钮,然后我的应用程序应该通过该 activePage 状态呈现任何处于活动状态的页面。

我被卡住了(应该强调我不确定什么是过度/覆盖或缺少的东西,我已经关注了一些关于动作/reducer/store 类型的在线教程(我打算这样做)一个调度调用,但似乎我可以直接从按钮单击调用 changePage 而不是调度(在实现调度时遇到问题))并且我一直在敲击桌子,以了解导入时如何未定义动作......也许我看的不正确……我是否遗漏了任何有助于诊断此错误的数据?:

TypeError:无法读取未定义的属性“类型” 所有减速机 .../client/src/redux/reducer/index.js:9 6 | activePage: '主页',

7 | }

8 |函数 allReducers(state = initState, action){

9 |开关(action.type){

10 |案例 CHANGE_PAGE:

11 |返回{

12 | ...状态,

loginButton.js

    const mapDispatchToProps = (state) => {
        return {
            changePage : state.activePage
        }
    };
    function LoginButtonThing (){
            return(
                <div>
                    <button onClick={() =>(changePage('loginPage'))}>Login Page</button>
                </div>
            )
    
    }
    //export default LoginButtonThing;
    export default connect(null,mapDispatchToProps)(LoginButtonThing);

actions.js

import { 
    CHANGE_PAGE, 
 } from "../constants/action-types";
export const changePage = (activePage) => ({
    type: CHANGE_PAGE,
    payload: {
        activePage,
    },
});

action-types.js

export const CHANGE_PAGE = "CHANGE_PAGE";

reducer/index.js

import {CHANGE_PAGE} from "../constants/action-types";
import {changePage} from "../actions/actions"
const initState = {
    activePage: 'HomePage',
}
function allReducers(state = initState, action){
    switch(action.type){
        case CHANGE_PAGE:
            return{
                ...state,
                activePage :action.payload.activePage,
            };
    }
}

//const store = createStore(rootReducer);

export default allReducers;

App.js

class App extends React.Component {
  render() {
    //this.props.activePage = 'HomePage';
    let renderedPage;
    if (this.props.changePage === "LoginPage") renderedPage = <LoginPage/>;
    else if (this.props.changePage === "HomePage") renderedPage = <HomePage/>;
    else renderedPage = <HomePage/>;
    //defaultStatus:activePage = "HomePage";
    return (
        <div id="App">
          {renderedPage}
        </div>
    );
  }
}

index.js

import {createStore, combineReducers} from 'redux';
import allReducers from "./redux/reducer"
//import LoginPage from "./loginPage";
import {Provider} from "react-redux";

const store = createStore(
    allReducers,
    window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);

ReactDOM.render(
    <Provider store = {store}>
        <React.StrictMode>
            <BrowserRouter>
                 <Route exact path="/" component = {HomePage}>
                    <Route path= "/loginPage" component ={LoginPage} />
                </Route>
             </BrowserRouter>
         <App />

  </React.StrictMode>
    </Provider>,
  document.getElementById('root')
);

【问题讨论】:

    标签: javascript reactjs redux navigation


    【解决方案1】:

    缺少默认情况

    如果调度了未知操作,您的减速器需要return state,例如将您的状态设置为初始值的“init”操作。

    function allReducers(state = initState, action) {
      switch (action.type) {
        case CHANGE_PAGE:
          return {
            ...state,
            activePage: action.payload.activePage
          };
        default:
          return state;
      }
    }
    

    混合状态和调度

    connect HOC 有两个参数:mapStateToPropsmapDispatchToProps。我认为这些名称是不言自明的。那么为什么你的mapDispatchToProps 函数将state 作为参数而不是dispatch

    如果使用connectLoginButtonThing 应该访问一个版本的changePage,该版本已经从其道具绑定到dispatch。您可以像这样使用action object shorthand

    import { connect } from "react-redux";
    import { changePage } from "../store/actions";
    
    function LoginButtonThing({ changePage }) {
      return (
        <div>
          <button onClick={() => changePage("loginPage")}>Login Page</button>
        </div>
      );
    }
    export default connect(null, { changePage })(LoginButtonThing);
    

    但是you should use hooks,像这样:

    import { useDispatch } from "react-redux";
    import { changePage } from "../store/actions";
    
    export default function LoginButtonThing() {
      const dispatch = useDispatch();
      return (
        <div>
          <button onClick={() => dispatch(changePage("loginPage"))}>Login Page</button>
        </div>
      );
    }
    

    命名不一致

    这实际上并没有导航到LoginPage 组件!那是因为LoginButtonThing 将页面更新为"loginPage"(小写),但App 正在寻找字符串"LoginPage"(大写)。


    不要这样做

    您的代码有很多问题,而且很多只是“过时”,我们现在有更好的方法,比如钩子和Redux-Toolkit

    我实际上认为像您尝试做的那样将导航状态移动到 Redux 不是一个好主意,我建议您坚持使用 react-router。你可以read here为什么你不需要或不想这样做。

    【讨论】:

    • 您好,谢谢您的意见!添加案例编辑调度/案例确实允许应用程序在点击时更改 activePage 状态。我认为我同意将导航迁移到 Redux 可能是一个坏主意,尽管我现在可能在兔子洞中太深了(可以这么说)。我想我会将 Redux 用于我的应用程序的其他状态,但希望将其作为概念证明(尽管公认不是最好的证明),并将在下一个实现中切换回 React-router。虽然点击它确实改变了状态,但应用程序似乎并没有呈现到正确的页面(停留在主页上)
    • @ArthurS 你解决了我提到的名称不匹配的问题吗? "loginPage""LoginPage"?这就是你不导航的原因。或许您应该使用.toLowerCase() 在您的App 组件中进行不区分大小写的匹配。
    • 是的我有(把App改成this.props.changePage === "loginPage", loginButton.js有onClick={() => dispatch(changePage("loginPage"))}) . Redux DevTools 说它确实在改变状态,但由于某种原因它似乎没有在状态改变时呈现它
    猜你喜欢
    • 2018-01-05
    • 2019-03-10
    • 2019-06-03
    • 2020-10-10
    • 2019-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-22
    相关资源
    最近更新 更多