#reactjs
#reactjs
Вопрос:
Я вхожу в reactjs и создаю простое приложение Todo, как показано ниже. Однако, когда я пытаюсь переключить флажок, они не переключаются, а также ошибка компиляции не отображается.
1. Used the following command to create app
command: npx create-react-app test-app
* Folder Structure
- node_modules
- publics
- src
- App.css
- App.js
- App.test.js
- index.css
- index.js
- TodoItem.js --
- todosData.js --
- ....
Я внес изменения только в 3 файла. Они App.js, TodoItems.js, todosData.js. Весь вставленный код взорван.
App.js
import React from "react"
import TodoItem from "./TodoItem"
import todosData from "./todosData"
class App extends React.Component {
constructor() {
super()
this.state = {
todos: todosData
}
this.handleChange = this.handleChange.bind(this)
}
handleChange(id) {
this.setState(prevState => {
const updatedTodos = prevState.todos.map(todo => {
if (todo.id === id) {
todo.completed = !todo.completed
}
return todo
})
return {
todos: updatedTodos
}
})
}
render() {
const todoItems = this.state.todos.map(item => <TodoItem key={item.id} item={item} handleChange={this.handleChange}/>)
return (
<div className="todo-list">
{todoItems}
</div>
)
}
}
export default App
TodoItems.js
import React from "react"
function TodoItem(props) {
return (
<div className="todo-item">
<input
type="checkbox"
checked={props.item.completed}
onChange={() => props.handleChange(props.item.id)}
/>
<p>{props.item.text}</p>
</div>
)
}
export default TodoItem
todosData.js
const todosData = [
{
id: 1,
text: "Take out the trash",
completed: true
},
{
id: 2,
text: "Grocery shopping",
completed: false
},
{
id: 3,
text: "Clean gecko tank",
completed: false
},
{
id: 4,
text: "Mow lawn",
completed: true
},
{
id: 5,
text: "Catch up on Arrested Development",
completed: false
}
]
export default todosData
Ответ №1:
Вот краткий рабочий фрагмент, иллюстрирующий функциональную реализацию вашей установки.
Он передает обратный вызов в setState
и использует Array.find()
для получения ссылки на задачу, которую мы хотим изменить на основе переданного id
.
<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
<div id="App"></div>
<script type="text/babel">
const { useState} = React;
const todosData = [
{
id: 1,
text: "Take out the trash",
completed: true
},
{
id: 2,
text: "Grocery shopping",
completed: false
},
{
id: 3,
text: "Clean gecko tank",
completed: false
},
{
id: 4,
text: "Mow lawn",
completed: true
},
{
id: 5,
text: "Catch up on Arrested Development",
completed: false
}
];
function App() {
const [todos, setTodos] = useState(todosData);
const handleChange = (id) => {
setTodos(prevTodos => {
const todo = prevTodos.find(todo => todo.id === id);
todo.completed = !todo.completed;
return [...prevTodos];
});
}
return (
<div className="todo-list">
{todos.map(item => <TodoItem key={item.id} item={item} handleChange={handleChange} />)}
</div>
)
}
function TodoItem({item, handleChange}) {
return (
<div className="todo-item">
<input
type="checkbox"
checked={item.completed}
onChange={() => handleChange(item.id)}
/>
<p>{item.text}</p>
</div>
)
}
ReactDOM.render(<App />, document.getElementById('App'));
</script>
Ответ №2:
Вы не передаете фактическое значение ввода / флажка в состояние, что упрощает вашу работу по сравнению с реализацией изменения значения самостоятельно.
import React from "react"
function TodoItem(props) {
return (
<div className="todo-item">
<input
type="checkbox"
checked={props.item.completed}
onChange={val=> props.handleChange(props.item.id, val.target.checked)}
/>
<p>{props.item.text}</p>
</div>
)
}
export default TodoItem
Также внесите небольшое изменение в handleChange, чтобы использовать как идентификатор, так и значение
handleChange(id, val) {
this.setState(prevState => {
const updatedTodos = prevState.todos.map(todo => {
if (todo.id === id) {
todo.completed = val
}
return todo
})
return {
todos: updatedTodos
}
})
}
Ответ №3:
Вы можете обрабатывать свое состояние следующим образом
handleChange = (id) => {
const currState = {
...this.state,
};
const upgratedTodo = currState.todos.map((todo) => {
if (todo.id === id) {
todo.completed = !todo.completed;
}
return todo;
});
this.setState({
todos: upgratedTodo,
})
};