Reactjs React-更新具有默认值的受控元素

Reactjs React-更新具有默认值的受控元素,reactjs,Reactjs,我已经到处找了,但似乎找不到解决这个问题的灵丹妙药 在我的应用程序中,我可以创建一个便条。我希望能够编辑/更新注释。音符的值通过道具传递。如何使用道具作为textarea的默认值,同时跟踪注释的新值 class Note extends Component { constructor(props) { super(props); this.state = { noteValue: '' }; this.saveNote = this.saveN

我已经到处找了,但似乎找不到解决这个问题的灵丹妙药

在我的应用程序中,我可以创建一个便条。我希望能够编辑/更新注释。音符的值通过道具传递。如何使用道具作为textarea的默认值,同时跟踪注释的新值

class Note extends Component {
  constructor(props) {
    super(props);

    this.state = {
      noteValue: ''
    };

    this.saveNote = this.saveNote.bind(this);
    this.updateNote = this.updateNote.bind(this);
  }

  saveNote() {
    // Saves the note
  }

  updateNote(e) {
    this.setState({ noteValue: e.target.value });
  }

  render() {
    console.log('ALREADY CREATED NOTE VALUE : ', this.props.note.value)
    return (
      <textarea
        // defaultValue={this.props.note.value} I want to be able to do this but I know I can't since it's controlled
        onChange={this.updateNote}
        value={this.state.noteValue}
      />
      <button onClick={this.saveNote}>Save</button>
    );
  }
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators({
    updateNote: NoteActions.updateNote,
  }, dispatch);
}

function mapStateToProps(state, props) {
  return {
    note: NoteSelectors.getNoteById(state, props)
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(Note);
类注释扩展组件{
建造师(道具){
超级(道具);
此.state={
注意值:“”
};
this.saveNote=this.saveNote.bind(this);
this.updateNote=this.updateNote.bind(this);
}
saveNote(){
//保存便条
}
更新日期(e){
this.setState({noteValue:e.target.value});
}
render(){
console.log('已创建注释值:',this.props.NOTE.VALUE)
返回(
拯救
);
}
}
功能图DispatchToprops(调度){
返回bindActionCreators({
updateNote:NoteActions.updateNote,
},派遣);
}
函数mapStateToProps(状态、道具){
返回{
注意:NoteSelectors.getNoteById(状态,道具)
}
}
导出默认连接(mapStateToProps、mapDispatchToProps)(注);
当字段/输入具有通过道具的默认值时,更新该字段/输入的最佳方法是什么

  • 在构造函数中执行
    this.state={…this.props}
    似乎不是正确的方法。所有的文章都说这是一种反模式
  • 我对使用
    getDerivedStateFromProps
    感到非常困惑

  • 您可以使用
    componentDidMount
    方法

    componentDidMount(){
       this.setState({ noteValue : this.props.note.value})
    }
    
    当组件完成加载时,您可以将
    noteValue
    设置为
    props
    中的值,在这种情况下,您不需要设置
    defaultValue
    ,而
    value
    属性将起作用

    更新时,您可以使用
    setState
    中的
    callback
    将更新后的值发送到父组件

    updateNote(e) {
        this.setState({ noteValue: e.target.value }, () => //call function from parent to update the change);
    }
    

    我可以通过以下方式想出另一个解决方案:

    this.state = {
      noteValue: ''
    };
    
    ....
    
    <textarea
      onChange={this.updateNote}
      value={this.state.noteValue || this.props.note.value || ''}
    />
    
    this.state={
    注意值:“”
    };
    ....
    

    由于空字符串是falsy(
    this.state.noteValue
    ),它将首先转到
    this.props.note.value
    ,如果不存在,它将以空字符串结束

    实际上,
    getDerivedStateFromProps
    生命周期方法正是针对这种情况的。它会监听组件道具的所有更改。每次道具改变都会触发。而且,您仍然应该在lifecycle方法中检查新需要的道具,以避免不必要地重新渲染

    返回值充当React的
    setState
    功能。它会立即更改组件的状态

    class Note extends Component
    {
      static getDerivedStateFromProps(newProps, currentState)
      {
        console.log(newProps); // also you can listen the changes for simple debugging
    
        if (newProps.noteValue !== currentState.noteValue)
        {
          return ({ noteValue: newProps.noteValue }); // it will make change the state with new prop value
        }
    
        return null; // if nothing changed
      }
    
    ....
    }
    

    我也看到了这种方法,但它总是会在第一次加载时导致第二次渲染。在这一点上,我宁愿在构造函数中设置它来避免额外的渲染。在构造函数中设置道具状态可能会导致未定义道具的问题,因为当道具准备好时(考虑来自API调用的数据),您的子构造函数可能会先执行。是的,我确实遇到了这个问题,必须使用三元来检查数据。我对我目前的解决方案不满意,但我只是继续往下看了一会儿。在这种情况下,当用户开始在文本区域键入内容时,我似乎必须更新我的便笺(从redux商店提取)。在他们点击save之前,我不想更新任何内容。相反,我希望在状态中跟踪他们的更新。听道具对我没有任何好处,因为它应该保持不变,直到我发出API调用来更新注释。您将仅将本地状态更新为currentNote变量。当他们保存便笺时,会触发redux state,您将从
    getDerivedStateFromProps
    中以defaultNote的形式获取新状态。当我在textarea中键入时,它将更新
    this.state.noteValue
    。这将导致
    getDerivedStateFromProps
    中的
    if
    语句触发。因此,值将始终是来自道具的值,文本区域文本将永远不会更改。我希望有帮助。我希望这个答案对你有所帮助。我认为如果小心使用,这是避免反模式的唯一方法。