× TypeError: Cannot read properties of undefined (reading 'getState')

Posted

技术标签:

【中文标题】× TypeError: Cannot read properties of undefined (reading \'getState\')【英文标题】:× TypeError: Cannot read properties of undefined (reading 'getState')× TypeError: Cannot read properties of undefined (reading 'getState') 【发布时间】:2021-11-08 09:43:54 【问题描述】:

我是初学者,正在学习 react 和 redux。我写了这个关于如何在 redux 中使用 connect.js 的演示。搜索此类问题,但我的代码没有正确答案。我有一个未定义的上下文。是错字吗?还是我以错误的方式传递了上下文?提前致谢。这是我的代码。

index.js

import React from "react";
import ReactDOM from "react-dom";
import store from "./store";

import  Provider  from "react-redux";
import App from "./App";

ReactDOM.render(
  <Provider store=store>
    <App />
  </Provider>,
  document.getElementById("root")
);

/store/index.js

import  createStore  from "redux";
import reducer from "./reducer.js";
const store = createStore(reducer);
export default store;

/store/reducer.js

import  ADD, SUB, MUL, DIV  from './constants.js'

// or initialState
const defaultState = 
  counter: 0


function reducer(state = defaultState, action) 
  switch (action.type) 
    case ADD:
      return ...state, counter: state.counter + action.num;
    case SUB:
      return ...state, counter: state.counter - action.num;
    case MUL:
      return ...state, counter: state.counter * action.num;
    case DIV:
      return ...state, counter: state.counter / action.num;
    default:
      return state;
  


export default reducer

connect.js

import React,  PureComponent  from "react";
import  StoreContext  from "./context";

export default function connect(mapStateToProps, mapDispatchToProps) 
  return function enhanceHOC(WrappedCpn) 
    class EnhanceCpn extends PureComponent 
      constructor(props, context) 
        super(props, context);
        console.log('connect props', props);
        console.log('connect context', context);  // context is undefined here
        this.state = 
          storeState: mapStateToProps(context.getState()),
        ;
      

      componentDidMount() 
        this.unSubscribe = this.context.subscribe(() => 
          this.setState(
            counter: mapStateToProps(this.context.getState()),
          );
        );
      

      componentWillUnmount() 
        this.unSubscribe();
      

      render() 
        return (
          <WrappedCpn
            ...this.props
            ...mapStateToProps(this.context.getState())
            ...mapDispatchToProps(this.context.dispatch)
          />
        );
      
    
    EnhanceCpn.contextType = StoreContext;
    return EnhanceCpn;
  ;

context.js

import React from "react";
const StoreContext = React.createContext();
export 
  StoreContext

App.js

import React,  PureComponent  from 'react'
import My from './pages/my'

export default class App extends PureComponent 
  constructor(props, context) 
    super(props, context);

    console.log('APP props', props);
    console.log('APP context', context); // context got value
  

  render() 
    return (
      <div>
        <My />
      </div>
    )
  

我的.js

import React,  PureComponent  from 'react'
import  sub, mul  from '../store/actionCreators'
import connect from '../utils/connect'

class My extends PureComponent 

  render() 
    return (
      <div>
      <h3>my</h3>
      <h3>counter:  this.props.counter </h3>
      <button onClick=e => this.props.subNum()>-2</button>
      <button onClick=e => this.props.mulNUm(5)>*5</button>
    </div>
    )
  


const mapStateToProps = state => (
  counter: state.counter
)

const mapDispatchToProps = dispatch => (
  subNum: (num = -2) => 
    dispatch(sub(num))
  ,
  mulNUm: num => 
    dispatch(mul(num))
  

)

export default connect(mapStateToProps, mapDispatchToProps)(My)

actionCreators.js

import  ADD, SUB, MUL, DIV  from './constants.js'

export function add(num) 
  return 
    type: ADD,
    num
  


export const sub = (num) => 
  return 
    type: SUB,
    num
  


export const mul = (num) => (
  type: MUL,
  num
)

export const div = num => (
  type: DIV,
  num
)

constants.js

const ADD = 'ADD_ACTION'
const SUB = 'SUB_ACTION'
const MUL = 'MUL_ACTION'
const DIV = 'DIV_ACTION'

export  ADD, SUB, MUL, DIV 

【问题讨论】:

你的actionCreators在哪里? 您是否想创建自己的connect HOC 来娱乐或其他什么?为什么不使用/利用react-redux?如果我没记错的话,React 不推荐使用 constructor(props, context) 签名。 我编辑我的问题并发布 actionCreators.js。是的,我正在尝试创建自己的连接 hoc。 App.js 中的构造函数(道具,上下文)正在工作 如果你正在学习redux,不妨学习modern style写reducers 【参考方案1】:

来自docs,这是关于Class.contextType 的内容:

可以为类的contextType 属性分配一个上下文对象 由React.createContext() 创建。使用此属性可以让您 使用该上下文类型的最接近的当前值 this.context。您可以在任何生命周期方法中引用它 包括渲染功能。

在您的情况下,您似乎只是缺少使用 context 道具将自定义 StoreContext 传递给 redux Provider

您需要执行以下操作:

import React from "react";
import ReactDOM from "react-dom";
import store from "./store";
import  StoreContext  from "./context";

import  Provider  from "react-redux";
import App from "./App";

ReactDOM.render(
  <Provider store=store context=StoreContext>
    <App />
  </Provider>,
  document.getElementById("root")
);

另见https://react-redux.js.org/using-react-redux/accessing-store#providing-custom-context

【讨论】:

感谢您的回答。 适合我【参考方案2】:

我遇到了同样的问题,并通过在与应用 Provider 的根组件相同的文件上创建存储来解决。示例代码如下:

 <Provider store=createStore(reducers)>
    <App />
 </Provider>

【讨论】:

以上是关于× TypeError: Cannot read properties of undefined (reading 'getState')的主要内容,如果未能解决你的问题,请参考以下文章

TypeError: Cannot read properties of undefined (reading 'app') (Flutter web app)

TypeError: Cannot read properties of undefined (reading 'length') - 想要解释为啥代码这样说

Uncaught (in promise) TypeError: Cannot read properties of null (reading 'fingerprint') Laravel Live

D3.js 一直遇到这个错误 TypeError: Cannot read properties of null (reading 'ownerDocument')?

React Material UI:Appbar 给出了 TypeError: Cannot read properties of undefined (reading '100')

TypeError: Cannot read property 'scrollIntoView' of null 如何解决?