1
votes

I'm trying to use React-Redux. I have a situation where one connected component (Coordinates.jsx) nested in another connected component (Canvas.jsx).

Source code https://github.com/RinatRezyapov/Vault-13.git (yarn install and then yarn start)

In parent component Canvas.jsx I dispatch an action in componentDidMount() which immutably change state.

Canvas.jsx

componentDidMount() { this.props.addCanvasSize(windowWidth, windowHeight)
}

The problem is that after changing state the child component Coordinates.jsx doesn't get updated and console.log shows undefined.

Coordinates.jsx

componentDidMount() { console.log(this.props.canvasSize) }

I'm sure that state is updated correctly (checked with Redux devTool) and I guess I didn't mutate state in reduced.

If I wrap console.log(this.props.canvasSize) in setTimeout then it shows coorect state.

index.js (store)

const store = createStore(reducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())

render(
<Provider store={store}>
<App />
</Provider>, 
document.getElementById('root'));

actions/index.js

export const addCanvasSizeAction = (windowWidth, windowHeight) => ({
type: 'ADD_CANVAS_SIZE',
windowWidth,
windowHeight
})

reducers/reducer.js

export const reducer = (state={}, action) => {
switch (action.type) {
    case 'ADD_CANVAS_SIZE':
    return Object.assign({}, state, {canvasSize: {canvasWidth: action.windowWidth, canvasHeight: action.windowHeight}})
    default: 
    return state
}
}

components/App.jsx

class App extends React.Component {
render() {
return (  
    <div>
            <CanvasCont />
    </div>
    )
}
} 

components/Canvas.jsx

class Canvas extends React.Component {
constructor(props) {
super(props);

}


componentDidMount() {
var windowWidth = window.innerWidth-100;
var windowHeight = window.innerHeight-100;
var createCanvas = document.createElement("canvas");
createCanvas.id = 'canvas';
createCanvas.width = windowWidth;
createCanvas.height = windowHeight;
ReactDOM.findDOMNode(this).appendChild(createCanvas);
var rect = canvas.getBoundingClientRect();
var ctx = createCanvas.getContext('2d');
 this.props.addCanvasSize(windowWidth, windowHeight)    
}



render() {
return (<div>
<CoordinatesCont />
</div>)
}
}

components/Coordinates.jsx

class Coordinates extends React.Component {

constructor(props) {
    super(props);

}
componentDidMount() {
console.log(this.props.canvasSize)
}
render() {

    var inlineStyle={
        width: "800px",
        height: "600px"
    }
       return (
    <div >
<span  style={inlineStyle} onMouseMove={this.handleMouseMove}></span>
    </div>
)
}
}

containers/CanvasCont.js

const mapStateToProps = (state) => ({
state: state
})

const mapDispatchToProps = (dispatch) => ({
addCanvasSize: (windowWidth, windowHeight) => 
{dispatch(addCanvasSizeAction(windowWidth, windowHeight))}
})

const CanvasCont = connect(
mapStateToProps,
mapDispatchToProps
)(Canvas)

containers/CoordinatesCont.js

const mapStateToProps = (state) => ({
canvasSize: state.canvasSize
})

const mapDispatchToProps = (dispatch) => ({
})

const CoordinatesCont = connect(
mapStateToProps,
mapDispatchToProps
)(Coordinates)
1
Please put the code necessary to diagnose potential problems in the post itself rather than pointing to an external repository. How it's connected matters, state shape matters.Dave Newton

1 Answers

2
votes

When dealing with parent/child relation, you should keep in mind that the componentDidMount is called on the children before it is called on the parent (as explained in this answer https://stackoverflow.com/a/38472793/2745879)

So actually in your case, here is what happens:

  1. the child triggers its componentDidMount callback but the state is not yet defined
  2. your console.log is triggered but there is nothing in the props
  3. the parent triggers its componentDidMount and update the state
  4. if you call console.log in a timeout in the child, now your properties are up to date

Now if you want to solve this, you need to use the componentWillReceiveProps callback that will be called whenever new properties are given to the component. https://facebook.github.io/react/docs/react-component.html#componentwillreceiveprops