如果连接到未更改的商店,则React componentDidUpdate方法将不会触发继承的props更改

Jon*_*alb 4 javascript reactjs redux react-redux

我希望我的组件知道是否已加载某个库.要知道从任何上下文我将它连接到我的商店的"库"减少器到我的组件.我还this.props.dataObject从调用组件的父级传递了一个配置对象.像这样:

class GoogleButton extends Component {
    render() {
        if (this.props.libraries.google) {
            return <a id='sharePost' className='google_icon'></a>
        } else {
            return null
        }
    }

    componentDidUpdate() {
        gapi.interactivepost.render('sharePost', this.props.dataObject)
    }
}

function mapStateToProps(state) {
    return { libraries: state.libraries }
}

export default connect(mapStateToProps)(GoogleButton)
Run Code Online (Sandbox Code Playgroud)

处理库状态的reducer是这样的:

let newState = {...state}
newState[action.libraryName] = action.state
return newState 
Run Code Online (Sandbox Code Playgroud)

当我改变库状态componentDidUpdate工作.问题是当我改变父母继承的道具时this.props.dataObject.在这种情况下,componentDidUpdate不会触发.如果我connect从组件中删除它,它按预期工作.我在这里错过了一些东西?

Dan*_*mov 7

很可能你的一些道具在组件外部发生变异.
例如,您可能会像这样渲染组件:

class Parent extends Component {
  constructor() {
    super()
    this.state = { libraries: {} }
  }

  handleClick() {
    // MUTATION!
    this.state.libraries.google = true

    // Normally this forces to update component anyway,
    // but React Redux will assume you never mutate
    // for performance reasons.

    this.setState({ libraries: this.state.libraries })
  }

  render() {
    return (
      <div onClick={() => this.handleClick()}>
        <GoogleButton libraries={this.state.libraries} />
      </div>
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

因为Redux应用程序处理不可变数据,所以对其props connect()使用浅等式检查以避免不必要的重新渲染.但是,如果您在应用中使用变异,则无法使用此功能.

您有两种选择:

不要突变任何事情

这是最好的选择.例如,而不是像

  handleClick() {
    this.state.libraries.google = true
    this.setState({ libraries: this.state.libraries })
  }
Run Code Online (Sandbox Code Playgroud)

你可以写

  handleClick() {
    this.setState({
      libraries: {
        ...this.state.libraries,
        google: true
      }
    })
  }
Run Code Online (Sandbox Code Playgroud)

这样我们就可以创建一个新对象,因此connect()不会忽略更改的引用.(我在此代码段中使用了对象扩展语法.)

禁用性能优化

更糟糕的选择是完全禁用由此产生的性能优化connect().然后你的道具会更新,即使你在父母中改变它们,但你的应用程序会更慢.为此,请替换

export default connect(mapStateToProps)(GoogleButton)
Run Code Online (Sandbox Code Playgroud)

export default connect(mapStateToProps, null, null, { pure: false })(GoogleButton)
Run Code Online (Sandbox Code Playgroud)

除非绝对必要,否则不要这样做.


Jon*_*alb 6

我解决了。我不是 100% 确定这是准确的,但我会解释。如果我有什么不对的地方,请纠正我。

我一直在想丹在他的回答中所说的肤浅的平等检查。问题就在那里。我从父对象传递了一个对象,并且该对象的嵌套元素发生了变化。对象保持不变。因此,使用connect带来的浅层相等性检查,组件将永远不会更新。

Object.assign({}, dataObject)当我传递道具时,我的解决方案是在父级使用中,因此我制作了另一个不同的对象。现在,浅层相等性检查可以比较它并在更新组件之前确定 props 已经改变了。