在React中通过改变父组件的Props更新子组件

5
我有一个组件,它的状态作为属性传递给子组件。我注意到即使父组件的状态被改变了,子组件也没有重新渲染。
根据官方 React 文档中利用 shouldComponentUpdate 的方式:
“第一次内部组件被渲染时,它将具有 {foo: 'bar'} 作为值属性。如果用户单击锚点,父组件的状态将更新为 {value: {foo: 'barbar'}},触发内部组件的重新渲染过程,该过程将接收 {foo: 'barbar'} 作为新值的属性。
问题在于,由于父组件和内部组件共享对同一对象的引用,当对象在 onClick 函数的第 2 行被突变时,内部组件拥有的属性也会发生更改。因此,当重新渲染过程开始并调用 shouldComponentUpdate 时,this.props.value.foo 将等于 nextProps.value.foo,因为实际上,this.props.value 引用与 nextProps.value 相同的对象。
因此,由于我们将错过属性上的更改并短路重新渲染过程,UI 将不会从'bar'更新为'barbar'。”
如果我不能使用 shouldComponentUpdate,我该如何强制子组件基于来自父组件的属性更改而重新渲染?
父组件
我希望子组件基于给定的 showDropzone 布尔值重新渲染。
     <Dropzone 
      onDrop={this.onDrop} 
      clearFile = {this.clearFile}
      showDropzone = {this.state.filePresent}/>

子组件

export default class Dropzone extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    const { onDrop } = this.props;
    const {showDropzone} = this.props;
    const {clearFile} = this.props;

    return (
      <div className="file-adder">
          <div className="preview">
            {{showDropzone}? 
            <Dropzone
              onDrop={onDrop}
              ref="dropzone">
            </Dropzone>           
            :<button type="button" 
            className="btn btn-primary"
            onClick={clearFile}>
            Clear File</button>}
        </div>
    </div>
    );
  }
}

你确定命名正确吗?子组件被称为Dropzone,但它的渲染函数也呈现了一个子<Dropzone>。 - wintvelt
2个回答

3
抱歉,您的代码存在许多错误。
首先(这是一个提示),请检查:
 const { onDrop } = this.props;
 const { showDropzone } = this.props;
 const { clearFile } = this.props;

你可以只写一行代码

 const { onDrop, showDropzone, clearFile } = this.props;

现在你的问题从这里开始:

你在花括号内使用了showDropzone,这就是问题所在,请将其删除

你的错误是{{showDropzone}? firstOption : anotherOption }

应改为{ showDropzone? firstOption : anotherOption }


另一个错误:

你在组件内部使用Dropzone组件,这是一个很大的错误

你不能在此处使用Dropzone组件{{showDropzone}? <Dropzone {...}/> : anotherOption },可以从另一个组件中使用它


最后我尝试调整你的代码,使其像这样:

父组件

{ this.state.filePresent
   ? <Dropzone onDrop={this.onDrop} />
   : <button
         type="button" 
         className="btn btn-primary"
         onClick={clearFile}
         children="Clear File"
     />
}

子组件

class Dropzone extends Component {
  render() {
    const { onDrop } = this.props;

    return (
      <div className="file-adder">
        <div className="preview" onDrop={onDrop} ref="dropzone">
          <p>Hi! This is Dropzone component</p>
        </div>
      </div>
    );
  }
}

export default Dropzone;

0
在子组件中,您使用了“showZone”而不是“showDropzone”。
谢谢。

谢谢!那只是我的小错误,我尝试了一下,它仍然不起作用。 - lost9123193
您是否想在“clearFile”按钮点击时更新该状态? - Rakesh
状态 showZone 在父组件中更新为 true 和 false。我可以更新父状态。我的问题在于子组件中,只有 <Dropzone> 组件显示。即使我使用 {{showDropzone}?来检查 showDropzone 是 true 还是 false,清除文件按钮也从未显示。 - lost9123193
请尝试在render方法中使用一个变量来表示该条件,并将该变量渲染到返回值中,同时将onclick与this绑定: render(){ var showButton = if(this.props.showDropzone){ showButton = <Dropzone onDrop={this.props.onDrop} ref="dropzone"> </Dropzone>
} else{ showButton = <button type="button" className="btn btn-primary" onClick={this.props.clearFile.bind(this)}> 清除文件</button> } return( <div>{showButton}</div> )}
- Rakesh
谢谢,我不确定语法是否正确,今晚我会处理这个问题。 - lost9123193

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接