×TypeError:无法读取未定义的属性(读取“”getState“”)

huus2vyu  于 2022-09-21  发布在  React
关注(0)|答案(4)|浏览(318)

我是一个初学者,学习React和重复。我写了这个关于如何在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>
    )
  }
}

My.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 }
72qzrwbm

72qzrwbm1#

从文档中,以下是它对Class.contextType的描述:
可以为类的contextType属性分配由React.createContext()创建的上下文对象。通过使用此属性,您可以使用this.context使用该上下文类型的最接近的当前值。您可以在任何生命周期方法中引用它,包括Render函数。

在您的情况下,您似乎只是错过了将您的自定义StoreContextcontext道具一起还原为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

ldioqlga

ldioqlga2#

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

<Provider store={createStore(reducers)}>
    <App />
 </Provider>
hrysbysz

hrysbysz3#

无法读取未定义的属性(正在读取‘getState’)

解决方案:

(1)在您的redux文件夹中创建一个文件store.js,您可以复制代码

import { createStore, applyMiddleware } from "redux";
    import logger from 'redux-logger';

    import rootReducer from "./root-reducer";

    const middlewares = [logger];

    const store = createStore(rootReducer, applyMiddleware(...middlewares));

    export default store;

(2)导入index.js文件即可

<Provider store={store}>
          <BrowserRouter>
             <App />
          </BrowserRouter>
      </Provider>
nwo49xxi

nwo49xxi4#

我有相同的问题,我只是必须改变,因为我有我的配置商店从这里

import { configureStore } from "@reduxjs/toolkit";
import basketReducer from "../slices/basketSlice";
export const store = configureStore({
  reducer: {
    basket: basketReducer,
       },
         });

对此

import { configureStore } from "@reduxjs/toolkit";
import basketReducer from "../slices/basketSlice";
export default configureStore({
 reducer: {
  basket: basketReducer,
    },
     });

这个方法对我很管用

相关问题