【问题标题】:How to edit an input in React?如何在 React 中编辑输入?
【发布时间】:2020-07-25 14:37:43
【问题描述】:

我可以专注于输入并修改文本。但是当我按下回车时,文本根本没有改变。我把代码留在后面。我有一份待办事项清单和一份已完成清单。当我编辑待办事项列表中的文本并按 Enter 键时,修改后的值会出现在我的控制台中,但是当我将待办事项发送到完成列表时返回原始值/文本

import React from "react";
import "../list.css";

class List extends React.Component {
  constructor(props) {
    super(props);
    this.textInput = React.createRef();
    this.state = {
      isEditing: false,
      textInput: this.props.value,
    };
    this.focusTextInput = this.focusTextInput.bind(this);
  }

  focusTextInput() {
    this.textInput.current.focus();
  }

  // handleOnSubmit(event) {
  // event.preventDefault();
  // let aa = this.state.textInput;
  // if (aa !== "") {
  //   this.setState({ items: [...this.props.items, aa] });
  //   console.log(aa);
  // }
  // }

  // componentDidUpdate() {
  //   this.handleOnSubmit();
  // }

  onChange = (event) => {
    // const textInput = this.textInput;
    this.setState({ textInput: event.target.value });
  };

  componentDidMount() {
    const editingState = true;
    if (!this.state.isEditing) {
      this.setState({ isEditing: editingState });
    }
  }

  render() {
    return (
      <ul>
        {this.props.title}
        {this.props.items.map((listItem, index) => {
          return (
            <li id="list-item" key={index}>
              <form onSubmit={(event) => this.onEdit(event)}>
                <input
                  type="text"
                  ref={this.textInput}
                  onChange={(event) => {
                    this.onChange(event);
                  }}
                  defaultValue={listItem}
                />
              </form>
              <button onClick={() => this.props.onAction(listItem)}>
                {this.props.label}
              </button>
              <button onClick={() => this.props.onDeleteItem(listItem)}>
                Delete
              </button>
              <button onClick={() => this.props.onSortItem(listItem)}>
                Sort
              </button>
              <button onClick={() => this.focusTextInput()}>Edit</button>
            </li>
          );
        })}
      </ul>
    );
  }
}

export default List;
import React from "react";
import Form from "./components/Form";
import List from "./components/List";
import "./App.css";

class App extends React.Component {
  state = {
    todoList: [],
    doneList: [],
  };

  addTodo = (value) => {
    if (value !== "") {
      this.setState({ todoList: [...this.state.todoList, value] });
    }
  };

  handleTodo = (value) => {
    const todoList = this.state.todoList.filter(
      (listValue) => listValue !== value
    );
    const doneList = [...this.state.doneList, value];
    this.setState({ todoList, doneList });
  };

  handleDone = (value) => {
    const doneList = this.state.doneList.filter(
      (listValue) => listValue !== value
    );
    const todoList = [...this.state.todoList, value];
    this.setState({ todoList, doneList });
  };

  deleteItem = (value) => {
    const doneList = this.state.doneList.filter(
      (listValue) => listValue !== value
    );
    const todoList = this.state.todoList.filter(
      (listValue) => listValue !== value
    );
    this.setState({ doneList, todoList });
  };

  sortItem = (value) => {
    const todoList = [value].concat(
      this.state.todoList.filter((item) => item !== value)
    );
    this.setState({ todoList });
  };

  editText = (event) => {
    event.preventDefault();
    let aa = this.props.textInput;
    if (aa !== "") {
      this.setState({ todoList: [...this.state.todoList, aa] });
      console.log(aa);
    }
  };

  render() {
    return (
      <div className="App">
        <Form onSubmit={this.addTodo} />
        <List
          onDeleteItem={this.deleteItem}
          onAction={this.handleTodo}
          items={this.state.todoList}
          onSortItem={this.sortItem}
          onEdit={this.editText}
          title="Todo"
          label="Done"
        />
        <List
          onDeleteItem={this.deleteItem}
          onAction={this.handleDone}
          items={this.state.doneList}
          title="Done"
          label="Todo"
        />
      </div>
    );
  }
}

export default App;

【问题讨论】:

标签: reactjs forms input edit


【解决方案1】:

我在这里看到了 2 个问题。您使用了错误的 key 属性,这使反应行为变得奇怪,而且您的方法 onAction 也是错误的,因为您没有以某种方式传递新值。

看看这个沙盒

https://codesandbox.io/s/wizardly-bhaskara-kiwpf

<li id="list-item" key={listItem}>

然后

<button onClick={() => this.props.onAction(listItem, this.state.textInput)}>

handleTodo = (originalValue, newValue) => {
    const todoList = this.state.todoList.filter(
      listValue => listValue !== originalValue
    );

const doneList = [...this.state.doneList, newValue ? newValue : originalValue];
    this.setState({ todoList, doneList });
  };

【讨论】:

  • 我不知道谁对我的回答投了反对票,但请分享您对自己行为的看法。
  • 编辑功能现在运行良好,但如果我将新项目添加到待办事项列表,然后将其传递给已完成列表,则文本消失导致元素未定义
  • @nicovg15 你是对的。请参阅我的更新答案。你需要检查 newValue 是否真的有一个值,这意味着你编辑了文本,否则,传递原始值。
  • 我刚刚发现,当我点击编辑按钮时,我在列表中选择哪一个并不重要,它总是会转到我添加的最后一项
  • 是的,这很奇怪。你能发布一个新问题吗?也许这是我现在找不到的东西,或者我不知道,但我想找出解决方案。如果您发布新问题,请在此处分享链接。谢谢!
【解决方案2】:

快速查看您的codesandbox,我认为问题出在您的List 组件中。在那里你映射到待办事项并提供index 作为键。我怀疑这就是问题所在。

React 使用这个键来优化渲染。这就是 React 如何快速找出哪些组件已更改、添加或删除的方式。当它是一个静态列表时, idx 很好,因为索引零将始终指向同一个组件。但是对于像您这样的流动列表,索引零可能不会指向相同的组件,这使得事情更难遵循。不过,作为最佳实践,最好使用唯一键。

为了让它工作,我只使用了todo 名称,但如果用户能够为多个待办事项使用相同的名称,您可能应该想办法。

您可以在此处阅读有关密钥的更多信息:https://reactjs.org/docs/lists-and-keys.html

【讨论】:

    【解决方案3】:

    @Apostolos

    https://codesandbox.io/s/wizardly-bhaskara-kiwpf

    感谢您的回答,但这似乎无法解决操作问题。当我编辑时,它什么也没做......也许我错过了一些东西。

    @nicovg15 这是一个根据您的沙箱进行编辑的工作示例。

    https://codesandbox.io/s/adoring-moser-4emfp?file=/src/components/listItem.jsx

    映射数据时最好使用新组件。例如,而不是这个

    {
      this.props.items.map((listItem, index) => {
        return (
          <li id="list-item" key={index}>
            <form onSubmit={(event) => this.onEdit(event)}>
              <input
                type="text"
                ref={this.textInput}
                onChange={(event) => {
                  this.onChange(event);
                }}
                defaultValue={listItem}
              />
            </form>
            <button onClick={() => this.props.onAction(listItem)}>
              {this.props.label}
            </button>
            <button onClick={() => this.props.onDeleteItem(listItem)}>
              Delete
            </button>
            <button onClick={() => this.props.onSortItem(listItem)}>Sort</button>
            <button onClick={() => this.focusTextInput()}>Edit</button>
          </li>
        );
      });
    }
    

    这样做

    {
      this.props.items.map((listItem, index) => (
        <li key={index}>
          <ListItem listItem={listItem} {...this.props} />
        </li>
      ));
    }
    

    这可确保您选择的项目将针对您选择的项目进行编辑、更新等。

    【讨论】:

    • 我只对一个按钮进行了更改以显示它是如何完成的。没有改变整个项目。你对我的回答投了反对票吗?
    • 用户遇到的问题是他无法将更改后的输入文本值从一个列表复制到另一个列表,反之亦然。所以我专注于这个问题。
    【解决方案4】:
    import React from "react";
    import List from "./stest";
    
    class App extends React.Component {
      state = {
        todoList: ["Test"],
        doneList: [],
      };
    
      addTodo = (value) => {
        if (value !== "") {
          this.setState({ todoList: [...this.state.todoList, value] });
        }
      };
    
      handleTodo = (value) => {
        const todoList = this.state.todoList.filter(
          (listValue) => listValue !== value
        );
        const doneList = [...this.state.doneList, value];
        this.setState({ todoList, doneList });
      };
    
      handleDone = (value) => {
        const doneList = this.state.doneList.filter(
          (listValue) => listValue !== value
        );
        const todoList = [...this.state.todoList, value];
        this.setState({ todoList, doneList });
      };
    
      deleteItem = (value) => {
        const doneList = this.state.doneList.filter(
          (listValue) => listValue !== value
        );
        const todoList = this.state.todoList.filter(
          (listValue) => listValue !== value
        );
        this.setState({ doneList, todoList });
      };
    
      sortItem = (value) => {
        const todoList = [value].concat(
          this.state.todoList.filter((item) => item !== value)
        );
        this.setState({ todoList });
      };
    
      editText = (event, listItem) => {
        console.log(event.target.value, listItem);
        event.preventDefault();
        let aa = event.target.value;
        let remtodo = this.state.todoList.filter((x) => x !== listItem);
        remtodo.push(aa);
        this.setState({ todoList: [...remtodo] });
    
        console.log(remtodo);
      };
    
      render() {
        return (
          <div className="App">
            <List
              onDeleteItem={this.deleteItem}
              onAction={this.handleTodo}
              items={this.state.todoList}
              onSortItem={this.sortItem}
              onEdit={this.editText}
              title="Todo"
              label="Done"
            />
            <List
              onDeleteItem={this.deleteItem}
              onAction={this.handleDone}
              items={this.state.doneList}
              title="Done"
              label="Todo"
            />
          </div>
        );
      }
    }
    
    export default App;
    
    import React from "react";
    
    
    class List extends React.Component {
      constructor(props) {
        super(props);
        this.textInput = React.createRef();
        this.state = {
          isEditing: false,
          textInput: this.props.value,
        };
        this.focusTextInput = this.focusTextInput.bind(this);
      }
    
      focusTextInput() {
        this.textInput.current.focus();
      }
    
      // handleOnSubmit(event) {
      // event.preventDefault();
      // let aa = this.state.textInput;
      // if (aa !== "") {
      //   this.setState({ items: [...this.props.items, aa] });
      //   console.log(aa);
      // }
      // }
    
      // componentDidUpdate() {
      //   this.handleOnSubmit();
      // }
    
      onChange = (event) => {
        // const textInput = this.textInput;
        this.setState({ textInput: event.target.value });
      };
    
      componentDidMount() {
        const editingState = true;
        if (!this.state.isEditing) {
          this.setState({ isEditing: editingState });
        }
      }
    
      render() {
        return (
          <ul>
            {this.props.title}
            {this.props.items.map((listItem, index) => {
              return (
                <li id="list-item" key={index}>
                  {/* <form onSubmit={(event) => this.onEdit(event)}> */}
                    <input
                      type="text"
                      ref={this.textInput}
                      onChange={(event) => {
                        this.props.onEdit(event,listItem)
                      }}
                      defaultValue={listItem}
                    />
                  {/* </form> */}
                  <button onClick={() => this.props.onAction(listItem)}>
                    {this.props.label}
                  </button>
                  <button onClick={() => this.props.onDeleteItem(listItem)}>
                    Delete
                  </button>
                  <button onClick={() => this.props.onSortItem(listItem)}>
                    Sort
                  </button>
                  <button onClick={() => this.focusTextInput()}>Edit</button>
                </li>
              );
            })}
          </ul>
        );
      }
    }
    
    export default List;
    
    
    Edit event has issue. I have changed and tested edit with test value. 
    

    【讨论】:

      猜你喜欢
      • 2021-06-19
      • 2016-06-28
      • 1970-01-01
      • 2017-11-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-22
      • 2014-06-05
      • 2015-02-11
      相关资源
      最近更新 更多