状态更改后,React-Redux 连接的组件不会更新



我正在尝试使用React-Redux。我遇到一个连接的组件(坐标.jsx)嵌套在另一个连接的组件(Canvas.jsx)中的情况。

源代码 https://github.com/RinatRezyapov/Vault-13.git(纱线安装,然后纱线启动)

在父组件Canvas.jsx中,我在componentDidMount()中调度一个操作,该操作不可变地更改状态。

画布.jsx

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

问题是在更改状态后,子组件Coordinates.jsx不会更新,控制台.log显示未定义

坐标.jsx

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

我确定状态已正确更新(使用 Redux devTool 检查),我想我没有在减少中改变状态。

如果我将console.log(this.props.canvasSize)包装在setTimeout中,那么它会显示coorect状态。

索引.js(商店)

const store = createStore(reducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())
render(
<Provider store={store}>
<App />
</Provider>, 
document.getElementById('root'));

操作/索引.js

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

减速器/减速器.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
}
}

组件/App.jsx

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

组件/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>)
}
}

组件/坐标.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>
)
}
}

容器/画布Cont.js

const mapStateToProps = (state) => ({
state: state
})
const mapDispatchToProps = (dispatch) => ({
addCanvasSize: (windowWidth, windowHeight) => 
{dispatch(addCanvasSizeAction(windowWidth, windowHeight))}
})
const CanvasCont = connect(
mapStateToProps,
mapDispatchToProps
)(Canvas)

容器/坐标续.js

const mapStateToProps = (state) => ({
canvasSize: state.canvasSize
})
const mapDispatchToProps = (dispatch) => ({
})
const CoordinatesCont = connect(
mapStateToProps,
mapDispatchToProps
)(Coordinates)

在处理父/子关系时,您应该记住,在调用父级之前,componentDidMount是对子项调用的(如本答案 https://stackoverflow.com/a/38472793/2745879 中所述)

所以实际上在你的情况下,这是发生的事情:

  1. 子项触发其componentDidMount回调,但状态尚未定义
  2. 您的console.log已触发,但props中没有任何内容
  3. 父级触发其componentDidMount并更新状态
  4. 如果您在子项超时时调用console.log,则现在您的属性是最新的

现在,如果要解决此问题,则需要使用每当为组件提供新属性时将调用的componentWillReceiveProps回调。 https://facebook.github.io/react/docs/react-component.html#componentwillreceiveprops

最新更新