如何设置 defaultValue,value={this.props.value},并使用 React 更新文本输入的值?

Spe*_*sys 6 javascript reactjs

概括:

我正在尝试使用 React 制作博客,但似乎在设置和更新文本字段时遇到了障碍。我有来自数据库的博客文本和用户名,并希望在文本窗口中为给定用户设置博客文本。然后当用户键入时,我也想更新该文本。

试图:

如果我设置我的 textarea value={this.props.name}它将正确设置该值但不会更新。如果我将它设置为更新,{this.state.value}那么它开始时为空白,但会正确更新。我可以找到有关如何设置默认值或更新值的示例。我无法弄清楚如何做到这两点。先感谢您。

应用程序内的 ClickScreen React 组件调用

<ClickScreen
    setClicks={this.setClicks}
    setUsername={this.setUsername}
    setBlog={this.setBlog}
    onLogout={this.onLogout}
    counter={this.state.counter}
    blogtext={this.state.blogtext}
    username={this.state.username}
/>
Run Code Online (Sandbox Code Playgroud)

在 ClickScreen 页面中的 BlogEntry React 组件调用:

<EditBlog name={this.props.blogtext} username={this.props.username} ></EditBlog>
Run Code Online (Sandbox Code Playgroud)

EditBlog 反应组件

// Allows a user to edit a blog entry.
var EditBlog = React.createClass({
  displayName: 'Editor',
  propTypes: {
    name: React.PropTypes.string.isRequired
  },
  getInitialState: function() { 
    console.log("getInitialState value: " + this.props.name);
    return {
      value: this.props.name,
    };
  },
  componentDidMount: function() {
         this.setState({value: this.props.name});
  },
  handleChange: function(event) {
    console.log("changing the text area to: " + event.target.value)
    this.setState({value: event.target.value});
  },
  updateBlogText: function() {
        ajax('update_blog.php', { blogtext: this.value, username: this.props.username }, function(response) {
            console.log("Updating blog text to: " + this.state.value + " with user: " + this.props.username);
            
            if (response.result === 'success') {
                console.log("Success!");
                //this.props.setClicks(response.counter, response.username, response.blogtext);
                //this.props.setUsername(response.username);
                //this.props.setBlog(response.blogtext);
            }
            else if (response.result === 'error') {
                alert('Error: ' + response.msg);
                console.log("Error!");
            }
            else {
                alert('Response message has no result attribute.');
            }
        }.bind(this));
        console.log("Click button clicked");
    },
  render: function() {
    console.log("this.state.value: " + this.state.value)
    console.log("this.state.value blogtext: " + this.props.name);
    this.state.value = this.props.value;
    return (
        <div>
            <h2>Blog Entry</h2>
            <center>
              <form id="noter-save-form" method="POST">
                <textarea id="noter-text-area" name="textarea"  onChange={this.handleChange} defaultValue={this.props.name}></textarea>
                <input type="submit" value="Save" onClick={this.updateBlogText}/>
              </form>
            </center>
        </div>
    );
  }
});
Run Code Online (Sandbox Code Playgroud)

更新: 我对受控和非受控 React 组件与 React 生命周期之间的区别的理解存在一些问题。现在该值在 getInitialState 中设置,然后在 componentWillReceiveProps 中适当更新。谢谢大家!

变化:

  • componentDidMount -> componentWillReceiveProps。这与 React 组件生命周期有关。
  • 文本区域defaultValue={this.props.name}已更改以反映 的更新状态值value={this.state.value}
  • this.state.value=this.props.value 在渲染功能中已被删除。
       // Allows a user to edit a blog entry.
        var EditBlog = React.createClass({
          displayName: 'Editor',
          propTypes: {
                name: React.PropTypes.string.isRequired
          },
          getInitialState: function() { 
            console.log("getInitialState value: " + this.props.name);
            return {
                value: this.props.name,
            };
          },
          componentWillReceiveProps: function(nextProps) {
                console.log("componentWillReceiveProps: " + nextProps.name);
                this.setState({value: nextProps.name});
          },
          handleChange: function(event) {
                console.log("changing the text area to: " + event.target.value);
                this.setState({value: event.target.value});
          },
          updateBlogText: function() {
                ajax('update_blog.php', { blogtext: this.value, username: this.props.username }, function(response) {
                    console.log("Updating blog text to: " + this.state.value + " with user: " + this.props.username);
                    
                    if (response.result === 'success') {
                        console.log("Success!");
                        //this.props.setClicks(response.counter, response.username, response.blogtext);
                        //this.props.setUsername(response.username);
                        //this.props.setBlog(response.blogtext);
                    }
                    else if (response.result === 'error') {
                        alert('Error: ' + response.msg);
                        console.log("Error!");
                    }
                    else {
                        alert('Response message has no result attribute.');
                    }
                }.bind(this));
                console.log("Click button clicked");
            },
          render: function() {
            return (
                <div>
                    <h2>Blog Entry</h2>
                    <center>
                      <form id="noter-save-form" method="POST">
                        <textarea id="noter-text-area" name="textarea"  onChange={this.handleChange} value={this.state.value}></textarea>
                        <input type="submit" value="Save" onClick={this.updateBlogText}/>
                      </form>
                    </center>
                </div>
            );
          }
        });
Run Code Online (Sandbox Code Playgroud)

Jor*_*rix 5

对于 React 中的表单:

defaultValue 和 defaultChecked 道具仅在初始渲染期间使用。如果您需要在后续渲染中更新该值,则需要使用受控组件。

有关受控组件的文档


小智 5

因此,无论何时您想编辑 props,您都必须将它们设置为本地组件状态(就像您在 getInitialState 中通过将 value 设置为 props 所做的那样)。道具是不可变的,因此将输入的值或默认值设置为道具将/不应允许您更改道具。

所以在下面,我所做的是将输入的值设置为 this.state.name,并将 this.state.name 在初始状态设置为 this.props.name,每当您调用 update 时,它​​都会更新组件状态输入中输入的任何内容。

如果您需要将名称传递回父组件,那么您需要从父组件传入一个函数,然后您可以从子组件调用该函数以通知父组件名称值已更改,然后父组件需要更新然后将名称传递回孩子...这创建了一个 2 路数据绑定..

// Allows a user to edit a blog entry.
var EditBlog = React.createClass({
  displayName: 'Editor',
  propTypes: {
    name: React.PropTypes.string.isRequired
  },
  getInitialState: function() { 
    console.log("getInitialState value: " + this.props.name);
    return {
      value: this.props.name,
    };
  },
  componentWillReceiveProps: function ( newProps ) {
    this.setState( { value:newProps.name } );
  }
  handleChange: function(event) {
    console.log("changing the text area to: " + event.target.value)
    this.setState({value: event.target.value});
  },
  updateBlogText: function() {
        ajax('update_blog.php', { blogtext: this.value, username: this.props.username }, function(response) {
            console.log("Updating blog text to: " + this.state.value + " with user: " + this.props.username);

            if (response.result === 'success') {
                console.log("Success!");
                //this.props.setClicks(response.counter, response.username, response.blogtext);
                //this.props.setUsername(response.username);
                //this.props.setBlog(response.blogtext);
            }
            else if (response.result === 'error') {
                alert('Error: ' + response.msg);
                console.log("Error!");
            }
            else {
                alert('Response message has no result attribute.');
            }
        }.bind(this));
        console.log("Click button clicked");
    },
  render: function() {
    console.log("this.state.value: " + this.state.value)
    console.log("this.state.value blogtext: " + this.props.name);
    this.state.value = this.props.value;
    return (
        <div>
            <h2>Blog Entry</h2>
            <center>
              <form id="noter-save-form" method="POST">
                <textarea id="noter-text-area" name="textarea"  onChange={this.handleChange} value={value}></textarea>
                <input type="submit" value="Save" onClick={this.updateBlogText}/>
              </form>
            </center>
        </div>
    );
  }
});
Run Code Online (Sandbox Code Playgroud)