【问题标题】:Clearing state and input values between parent and child components in React在 React 中清除父子组件之间的状态和输入值
【发布时间】:2019-07-26 05:46:01
【问题描述】:

这里有两部分问题:首先,任何人都可以向我解释为什么 this.state.taskName 和 this.state.taskBody 以及它们相应的输入在提交表单后没有清除吗?在 handleSubmit() 中,我使用 this.setState() 将它们的状态设置为空字符串,但它似乎不起作用。它也不会让我多次提交,我怀疑这可能与状态未清除有关。

其次,将具有多个键值对的任务推送到 this.state.tasks 数组中的最佳方法是什么?我尝试将 taskName 和 taskBody 存储为 state 中的对象,还尝试将它们推送到对象中然后显示它们,但无法使其工作。

以下是父文件、子文件和兄弟文件:

import React, { Component } from 'react';
import Task from './Task/Task';
import NewTaskForm from './NewTaskForm/NewTaskForm';

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

        this.handleSubmit = this.handleSubmit.bind(this);
        this.handleChange = this.handleChange.bind(this);

        this.state = {
            tasks: [],
            taskName: '',
            taskBody: ''
        };
    }

    handleSubmit(e) {
        e.preventDefault();
        let updatedTasks = this.state.tasks;
        let taskName = this.state.taskName;
        let taskBody = this.state.taskBody;

        updatedTasks.push(taskName, taskBody);
        let updatedName = '';
        let updatedBody = '';
        this.setState({ tasks: updatedTasks, taskName: updatedName, taskBody: updatedBody });
    };

    handleChange(e) {
        this.setState({ [e.name]: e.value });
    }

    render() {
        return (
            <div>
                <NewTaskForm
                    onSubmit={this.handleSubmit}
                    onChange={this.handleChange}
                />
                <Task
                    tasks={this.state.tasks}
                />
            </div>
        );
    }
}

export default Board;


import React, { Component } from 'react';

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

        this.handleChange = this.handleChange.bind(this);
    }

    handleChange(e) {
        this.props.onChange(e.target);
    }

    render() {
        return (
            <form onSubmit={this.props.onSubmit}>
                <label>Task Name</label>
                <input
                    name="taskName"
                    required type="text"
                    value={this.props.taskName}
                    onChange={this.handleChange}
                    placeholder="Enter a task name"
                />

                <label>Task Body</label>
                <input
                    name="taskBody"
                    required type="text"
                    value={this.props.taskBody}
                    onChange={this.handleChange}
                    placeholder="Enter a task body"
                />

                <button
                    type="submit"
                    className="btn btn-default"
                >Add Task
                </button>
            </form>
        );
    }
}

export default NewTaskForm;


import React, { Component } from 'react';

class Task extends Component {
    render() {
        let taskList = this.props.tasks.map((task, i) => {
            return (
                <li key={i}>
                    {task}
                </li>
            );
        });
        return (
            <ul>
                {taskList}
            </ul>
        )
    }
}

export default Task;

谢谢!

【问题讨论】:

  • 据我所知,this.props.taskNamethis.props.taskBody 未定义,因为您没有将它们传递给 &lt;NewTaskForm&gt;

标签: javascript reactjs input state


【解决方案1】:

为了解决您的第一个问题,输入未清除的原因是因为您没有将 taskNametaskBody 值作为道具传递给 &lt;NewTaskForm /&gt;。输入不受 React 控制,因为 NewTaskForm 没有接收它们,因此它们目前完全由用户控制。添加它们,您将在提交表单后看到它们。

保持taskName/taskBody 对处于状态的最佳方式是如您所说:一个对象。不过,在您的TaskComponent 中,您需要更改映射逻辑以使用对象,并确保将对象推送到Board 中的this.state.tasks。我已链接到显示我所做更改的 Fiddle:https://jsfiddle.net/0z89Lcpw/

具体而言,我对您的代码所做的更改是:

  • 修改第 21 行以推送形状为 {taskName, taskBody} 的对象
  • 添加了第 37 和 38 行以将 taskNametaskBody 属性传递给 NewTaskForm
  • 更改了第 95 行(旧:第 93 行)以将 taskNametaskBody 从每个任务中提取出来并同时呈现两者——当然,您可以以多种不同的方式呈现这些数据,以满足您的演示目的.

【讨论】:

    【解决方案2】:

    我会尝试这样的事情:

    handleSubmit(e) {
        e.preventDefault();
        const { taskName, taskBody } = this.state;
        this.setState({ 
            tasks: [...this.state.tasks, { taskName, taskBody }] 
            taskName: '', 
            taskBody: '' 
        });
    };
    

    这样你就不会改变你的状态并且你的数组包含每个任务一个对象。

    【讨论】:

      【解决方案3】:

      我可以看到您编写代码的方式存在一些问题。对于初学者,您不会将taskNametaskBody 作为道具传递给NewTaskForm,因为组件希望从道具中读取值。

      • 改变状态不是一个好主意
      • 正如名称和身体包含在一项任务中一样,保持它的形状。

      检查此代码 sn-p - https://codesandbox.io/s/ov675m6r7y

      【讨论】:

        【解决方案4】:

        请在下方查看您更改后的代码。我在下面为我所做的主要改动添加了解释:)

        class Board extends React.Component {
          constructor(props) {
            super(props);
        
            this.state = {
              tasks: [],
              taskName: '',
              taskBody: ''
            };
          }
        
          handleSubmit(e) {
            e.preventDefault();
        
            let tasks = this.state.tasks;
            let taskName = this.state.taskName;
            let taskBody = this.state.taskBody;
        
            tasks.push({taskName, taskBody});
        
            this.setState({tasks, taskName: '', taskBody: ''});
          };
        
          handleChange(e) {
            const name = e.target.name; 
            const value = e.target.value;
        
            this.setState({[name]: value});
          }
        
          render() {
            return (
              <div>
                <NewTaskForm
                  taskName={this.state.taskName}
                  taskBody={this.state.taskBody}
                  onSubmit={(e) => this.handleSubmit(e)}
                  onChange={(e) => this.handleChange(e)}
                />
                <Tasks
                  tasks={this.state.tasks}
                />
              </div>
            );
          }
        }
        
        class NewTaskForm extends React.Component {
          render() {
            return (
              <form onSubmit={this.props.onSubmit}>
                <label>Task Name</label>
                <input
                  name="taskName"
                  required type="text"
                  value={this.props.taskName}
                  onChange={(e) => this.props.onChange(e)}
                  placeholder="Enter a task name"
                />
        
                <label>Task Body</label>
                <input
                  name="taskBody"
                  required type="text"
                  value={this.props.taskBody}
                  onChange={(e) => this.props.onChange(e)}
                  placeholder="Enter a task body"
                />
        
                <button type="submit" className="btn btn-default">Add Task</button>
              </form>
            );
          }
        }
        
        class Tasks extends React.Component {
          render() {
            let taskList = this.props.tasks.map((task, i) => {
              return (
                <li key={i}>
                  <b>{task.taskName}</b><br/>
                  {task.taskBody}
                </li>
              );
            });
        
            return (
              <ul>
                {taskList}
              </ul>
            )
          }
        }
        
        1. 通过 taskName 和 taskBody 作为道具传递给您的 NewTaskForm 在他们的输入中使用的组件。
        2. 您错误地将新任务推送到更新的任务列表中。
        3. 在您的任务组件中,您没有显示 任务,您正试图显示任务对象。

        工作小提琴:https://jsfiddle.net/8sLw4phf/2/

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-01-25
          • 2020-06-24
          • 2019-08-03
          • 2020-08-07
          • 1970-01-01
          • 2023-01-19
          • 1970-01-01
          • 2018-08-10
          相关资源
          最近更新 更多