#javascript #reactjs
Вопрос:
У меня есть простое в использовании приложение в react, все в порядке, когда моя app.js является компонентом класса, но когда я изменил его на функциональный компонент, возникла ошибка = todos.фильтр — это не функция
мои файлы : Todo.js(функционально) —> TodoList.js(функционально) —>> app.js(функциональный)
function TodoList(props) {
const [statusDone, setDone] = useState(false);
let { todos } = props;
console.log(todos);
let filterTodos = todos.filter((item) => item.done === statusDone);
return (
<>
<nav className="col-6 mb-3">
<div className="nav nav-tabs" id="nav-tab" role="tablist">
<a
className={`nav-item nav-link font-weight-bold ${
!statusDone ? "active" : ""
}`}
id="nav-home-tab"
onClick={() => setDone(false)}
>
undone{" "}
<span className="badge badge-secondary">
{todos.filter((item) => item.done === false).length}
</span>
</a>
<a
className={`nav-item nav-link font-weight-bold ${
statusDone ? "active" : ""
}`}
id="nav-profile-tab"
onClick={() => setDone(true)}
>
done{" "}
<span className="badge badge-success">
{todos.filter((item) => item.done === true).length}
</span>
</a>
</div>
</nav>
{filterTodos.length === 0 ? (
<p>there isn`t any todos</p>
) : (
filterTodos.map((item) => (
<Todo
key={item.key}
item={item}
delete={props.delete}
done={props.done}
edit={props.edit}
/>
))
)}
</>
);
}
основной класс приложения
function App() {
const [todos, settodos] = useState([]);
let addTo = (text) => {
settodos((prevState) => {
return {
todos: [prevState.todos, { key: Date.now(), done: false, text }],
};
});
};
return (
<div className="App">
<main>
<section className="jumbotron">
<div className="container d-flex flex-column align-items-center">
<h1 className="jumbotron-heading">Welcome!</h1>
<p className="lead text-muted">
To get started, add some items to your list:
</p>
<FormAddTodo add={addTo} />
</div>
</section>
<div className="todosList">
<div className="container">
<div className="d-flex flex-column align-items-center ">
<TodoList
todos={todos}
// delete={this.deleteTodo.bind(this)}
// done={this.toggleTodo.bind(this)}
// edit={this.editTodo.bind(this)}
/>
</div>
</div>
</div>
</main>
</div>
);
}
Я пытался
let filterTodos =Object.values(todos).filter(item => item.done === statusDone)
и исправлена ошибка, но мой код не работает верно
Надеюсь, вы понимаете, что я сказал 🙂
этот функциональный компонент предназначен для добавления задачи
function FormAddTodo(props) {
const [text, setText] = useState("");
let formHandler = (e) => {
e.preventDefault();
props.add(text);
setText("");
};
let inputHandler = (e) => setText(e.target.value);
return (
<form className="form-inline mb-5" onSubmit={formHandler}>
<div className="row form-group">
<div className="col-8">
<input
type="text"
className=" form-control mx-sm-3"
placeholder="i want to do ..."
value={text}
onChange={inputHandler}
/>
</div>
<div className="col-4">
<button type="submit" className=" btn btn-primary">
add
</button>
</div>
</div>
</form>
);
}
Комментарии:
1. Ваши
console.log(todos)
возвраты-это что-то? Я имею в виду, что данные присутствуют вtodos
?2. Пожалуйста, добавьте
App.js
код тоже3. @GiovanniEsposito, если я изменю все задачи в списке задач на Object.values(todos), то, когда я что-то добавлю, он вернет объект, содержащий задачу
4. @AndresGardiol спасибо ,я отредактировал его
5. @GiovanniEsposito ну, у меня есть форма, в которой мне нужно отправить значение ввода, у меня есть функция добавления App.js
Ответ №1:
Проблема в addTo
функционировании. Вы не добавляете элемент в todos
массив, но вы устанавливаете todos
в качестве объекта ключ под названием todos, содержащий массив. Попробуйте изменить addTo
функцию таким образом:
const addTo = (text) => {
let newElement = { key: Date.now(), done: false, text: text };
settodos(prevState => [...prevState, newElement]);
};
Ответ №2:
У вас здесь ошибка:
function App() {
const [todos, settodos] = useState([]);
let addTo = (text) => {
settodos((prevState) => {
return {
todos: [prevState.todos, { key: Date.now(), done: false, text }],
};
});
};
ваша функция мутации в settodos
может попытаться объединить prevState.todos с новым заданием.
на самом деле с помощью задатчика useState вы получаете значение напрямую:
settodos(currentTodos => ...)
затем верните значение, которое вы хотите (вы возвращаете объект вместо массива)
кроме того, если вы хотите объединить два массива, используйте оператор распространения:
const newArray = [...someArray, newValue];
итак, подводя итог, вот исправленная версия этого фрагмента кода:
function App() {
const [todos, settodos] = useState([]);
let addTo = (text) => {
settodos((prevTodos) => [
...prevTodos,
{ key: Date.now(), done: false, text }
]);
};