Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
111
rated 0 times [  116] [ 5]  / answers: 1 / hits: 27093  / 3 Years ago, mon, september 13, 2021, 12:00:00

I am a beginner learning react and redux. I wrote this demo about how to use connect.js in redux. Searching this kind of question but there is no right answer for my code. I got a undefined context. Is it typo? or I passed context in a wrong way? Thanks in advance. Here is my code.


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 }

More From » reactjs

 Answers
47

From the docs, here is what it says with regards to Class.contextType:



The contextType property on a class can be assigned a Context object
created by React.createContext(). Using this property lets you
consume the nearest current value of that Context type using
this.context. You can reference this in any of the lifecycle methods
including the render function.



It seems that in your case, you are just missing passing your custom StoreContext to redux Provider with the context props


You need to do something like:


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

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


[#50178] Monday, August 23, 2021, 3 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
daja

Total Points: 407
Total Questions: 103
Total Answers: 103

Location: Ghana
Member since Sun, Mar 27, 2022
2 Years ago
daja questions
Tue, Dec 21, 21, 00:00, 2 Years ago
Thu, Apr 23, 20, 00:00, 4 Years ago
Fri, Sep 6, 19, 00:00, 5 Years ago
Tue, Jul 23, 19, 00:00, 5 Years ago
;