【问题标题】:React-Redux connected component doesn't get updated after state is changedReact-Redux 连接组件在状态更改后不会更新
【发布时间】:2017-05-24 15:32:57
【问题描述】:

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

源码https://github.com/RinatRezyapov/Vault-13.git(yarn install 然后yarn start)

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

Canvas.jsx

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

问题是在更改状态后,子组件 Coordinates.jsx 没有得到更新,并且 console.log 显示 undefined

坐标.jsx

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

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

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

index.js(商店)

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>
)
}
}

容器/CanvasCont.js

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

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

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

容器/CoordinatesCont.js

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

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

const CoordinatesCont = connect(
mapStateToProps,
mapDispatchToProps
)(Coordinates)

【问题讨论】:

  • 请将诊断潜在问题所需的代码放在帖子本身,而不是指向外部存储库。它的连接方式很重要,状态形状很重要。

标签: javascript reactjs redux react-redux


【解决方案1】:

在处理父/子关系时,您应该记住,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

【讨论】:

  • 不知道先调用child的componentDidMount。谢谢你的信息,现在我知道会发生什么。这意味着在这种情况下更新子组件的唯一方法是检查 nextProps 然后强制更新组件?还有其他方法可以使组件保持最新状态吗?也许在 App 组件中嵌套 Canvas 和 Coordinates(我的意思是摆脱父/子关系?)
  • 哦,不,我认为您无需更改任何内容。要确信一切都按预期工作,请尝试在子组件的render 函数中添加console.log(this.props),您将看到(如果我是正确的)2 个记录第一个是undefined,另一个是正确的canvasSize
  • @GalaxyWanderer 有道理,对吧?必须先安装组件的子组件,然后才能将父组件视为已安装。
猜你喜欢
  • 2019-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-12
  • 1970-01-01
相关资源
最近更新 更多