如何在 React 中编辑输入?
How to edit an input in React?
我现在可以专注于输入和修改文本。但是当我按下回车键时,文本根本没有改变。我把代码留在后面。我有一份待办事项清单和一份已完成清单。当我编辑待办事项列表中的文本并按回车键时,修改后的值会出现在我的控制台中,但是当我将待办事项发送到已完成列表时 return 原来的 value/text
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;
快速查看了您的 codesandbox
,我认为问题出在您的 List
组件中。在那里,您映射待办事项并提供 index
作为键。我怀疑这是问题所在。
React 使用这个键来优化渲染。这就是 React 可以快速找出哪些组件已更改、添加或删除的方式。当它是静态列表时,idx 很好,因为索引零将始终指向同一组件。但是对于像您这样的流动列表,索引零可能不会指向相同的组件,这使得事情更难遵循。不过,作为最佳实践,最好始终使用唯一键。
为了让它工作,我只使用了 todo
名称,但如果用户能够对多个待办事项使用相同的名称,您可能应该想出别的办法。
您可以在此处阅读有关密钥的更多信息:https://reactjs.org/docs/lists-and-keys.html
我在这里看到 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 });
};
@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>
));
}
这确保您 select 的项目将针对您 select 的项目进行编辑、更新等。
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.
我现在可以专注于输入和修改文本。但是当我按下回车键时,文本根本没有改变。我把代码留在后面。我有一份待办事项清单和一份已完成清单。当我编辑待办事项列表中的文本并按回车键时,修改后的值会出现在我的控制台中,但是当我将待办事项发送到已完成列表时 return 原来的 value/text
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;
快速查看了您的 codesandbox
,我认为问题出在您的 List
组件中。在那里,您映射待办事项并提供 index
作为键。我怀疑这是问题所在。
React 使用这个键来优化渲染。这就是 React 可以快速找出哪些组件已更改、添加或删除的方式。当它是静态列表时,idx 很好,因为索引零将始终指向同一组件。但是对于像您这样的流动列表,索引零可能不会指向相同的组件,这使得事情更难遵循。不过,作为最佳实践,最好始终使用唯一键。
为了让它工作,我只使用了 todo
名称,但如果用户能够对多个待办事项使用相同的名称,您可能应该想出别的办法。
您可以在此处阅读有关密钥的更多信息:https://reactjs.org/docs/lists-and-keys.html
我在这里看到 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 });
};
@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>
));
}
这确保您 select 的项目将针对您 select 的项目进行编辑、更新等。
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.