Как сделать фильтрацию?
Как сделать фильтрацию на реакте?
todos приходит из компонента App, не могу присвоит значение в State всегда получаю undefined.
Может это из-за асинхронности?
const [newTodos, setNewTodos] = useState(todos);
Хотелось бы с помощью state сделать фильтрацию, сортировку и поиск.
export const TodoContext = createContext(); function App() { const [todos, setTodos] = useState([]); function addTask(task) { const newTodos = [task, ...todos]; setTodos(newTodos.sort((a, b) => a.checked - b.checked)); } function deleteTask(index) { setTodos(todos.filter((_, inx) => inx !== index)); } function onChecked(inx) { const newTodos = todos.map((todo, i) => { if (i === inx) { return { ...todo, checked: !todo.checked, }; } return todo; }); setTodos(newTodos.sort((a, b) => a.checked - b.checked)); } useEffect(() => { const localTodos = localStorage.getItem("todos") || []; setTodos(JSON.parse(localTodos)); }, []); useEffect(() => { localStorage.setItem("todos", JSON.stringify(todos)); }, [todos]); return ( <TodoContext.Provider value={todos}> <div className="todos container"> <Form addTask={addTask} /> <Todos deleteTask={deleteTask} onChecked={onChecked} /> </div> </TodoContext.Provider> ); } |
export const TodoContext = createContext(); function App() { const [todos, setTodos] = useState([]); function addTask(task) { const newTodos = [task, ...todos]; setTodos(newTodos.sort((a, b) => a.checked - b.checked)); } function deleteTask(index) { setTodos(todos.filter((_, inx) => inx !== index)); } function onChecked(inx) { const newTodos = todos.map((todo, i) => { if (i === inx) { return { ...todo, checked: !todo.checked, }; } return todo; }); setTodos(newTodos.sort((a, b) => a.checked - b.checked)); } useEffect(() => { const localTodos = localStorage.getItem("todos") || []; setTodos(JSON.parse(localTodos)); }, []); useEffect(() => { localStorage.setItem("todos", JSON.stringify(todos)); }, [todos]); return ( <TodoContext.Provider value={todos}> <div className="todos container"> <Form addTask={addTask} /> <Todos deleteTask={deleteTask} onChecked={onChecked} /> </div> </TodoContext.Provider> ); }
const Todos = ({ deleteTask, onChecked }) => { const todos = useContext(TodoContext); return ( <div className="todos__tasks "> <form className="todos__form"> <input className="todos__form-search" type="search" placeholder="Поиск" /> </form> <div className="todos__header"> <div className="todos__sorts"> <span className="todos__sorts-item">по названию</span> <span className="todos__sorts-item">по времени</span> </div> <select className="todos__filter"> <option className="todos__filter-item" value="all"> Все </option> <option className="todos__filter-item" value="checked"> Выполненные </option> <option className="todos__filter-item" value="notChecked"> Не выполненные </option> </select> </div> {todos.length !== 0 ? ( todos.map((todo, inx) => ( <Task key={inx} inx={inx} task={todo} deleteTask={deleteTask} onChecked={onChecked} /> )) ) : ( <h3 style={{ marginTop: "30px" }}>Задачи пока нету</h3> )} </div> ); }; |
const Todos = ({ deleteTask, onChecked }) => { const todos = useContext(TodoContext); return ( <div className="todos__tasks "> <form className="todos__form"> <input className="todos__form-search" type="search" placeholder="Поиск" /> </form> <div className="todos__header"> <div className="todos__sorts"> <span className="todos__sorts-item">по названию</span> <span className="todos__sorts-item">по времени</span> </div> <select className="todos__filter"> <option className="todos__filter-item" value="all"> Все </option> <option className="todos__filter-item" value="checked"> Выполненные </option> <option className="todos__filter-item" value="notChecked"> Не выполненные </option> </select> </div> {todos.length !== 0 ? ( todos.map((todo, inx) => ( <Task key={inx} inx={inx} task={todo} deleteTask={deleteTask} onChecked={onChecked} /> )) ) : ( <h3 style={{ marginTop: "30px" }}>Задачи пока нету</h3> )} </div> ); };
Дополнительно:
Очистите код от лишнего, приведите код App (тоже желательно без ненужных элементов)
const localTodos = localStorage.getItem("todos") || []; -> const localTodos = localStorage.getItem("todos") || '[]'; |
const localTodos = localStorage.getItem("todos") || []; -> const localTodos = localStorage.getItem("todos") || '[]';
В остальном всё должно работать.
Чтоб сделать фильтрацию просто делаешь так:
const [selected, setSelected] = useState('all'); let filterdTodos; switch(selected) { case 'all': filterdTodos = todos; break; case 'checked': filterdTodos = todos.filter(t => t.checked); break; case 'notChecked': filterdTodos = todos.filter(t => !t.checked); break; } |
const [selected, setSelected] = useState('all'); let filterdTodos; switch(selected) { case 'all': filterdTodos = todos; break; case 'checked': filterdTodos = todos.filter(t => t.checked); break; case 'notChecked': filterdTodos = todos.filter(t => !t.checked); break; }
Или так, с оптимизацией:
const [selected, setSelected] = useState('all'); const filterdTodos = useMemo(() => { switch(selected) { case 'all': return todos; case 'checked': return todos.filter(t => t.checked); case 'notChecked': return todos.filter(t => !t.checked); } }, [selected, todos]) |
const [selected, setSelected] = useState('all'); const filterdTodos = useMemo(() => { switch(selected) { case 'all': return todos; case 'checked': return todos.filter(t => t.checked); case 'notChecked': return todos.filter(t => !t.checked); } }, [selected, todos])
<select className="todos__filter" onChange={(event) =>setSelected(event.target.value)}> ... {filterdTodos.map(...)} |
<select className="todos__filter" onChange={(event) =>setSelected(event.target.value)}> ... {filterdTodos.map(...)}
- Сочнейший сок прям, все заработал здесь я понял как работает рендер и его преимущества, а как взять данные из контекста и сохранить в стеит? или так нельзя?
Просто помимо фильтрации есть еще сортировка и поиск, а массив просто не рендерится после поиска или сортировки. - Диас Галымбек, ты всё-таки что-то через зад пытаешься сделать. Контекст надо использовать, а на сохранять локально.
Возможно ты хочешь изменять контекст изнутри - тогда просто пробрасывавший в него вышестоящий setState и вызывай когда надо.Если очень хочется то както-так:
const todos = useContext(TodoContext); const [localTodos, setLocalTodos] = useState(todos); useEffect(() => setLocalTodos(todos), [todos]);
const todos = useContext(TodoContext); const [localTodos, setLocalTodos] = useState(todos); useEffect(() => setLocalTodos(todos), [todos]);
Но это плохо.
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
Для реализации фильтрации на веб-сайте можно использовать различные методы, в зависимости от требований проекта. Ниже приведен пример использования PHP для создания фильтра на странице.
Для начала создадим форму на странице, через которую пользователь будет выбирать параметры для фильтрации:
Category 1 Category 2 Category 3Category 1 Category 2 Category 3
Затем на серверной стороне обработаем данные формы и выполним фильтрацию:
<?php // Получаем данные из формы $search = isset($_GET['search']) ? $_GET['search'] : ''; $category = isset($_GET['category']) ? $_GET['category'] : ''; // Выполняем запрос к базе данных с учетом выбранных параметров $query = "SELECT * FROM products WHERE 1=1"; if (!empty($search)) { $query .= " AND name LIKE '%$search%'"; } if (!empty($category)) { $query .= " AND category_id = '$category'"; } // Выполняем запрос $result = mysqli_query($connection, $query); // Выводим результаты while ($row = mysqli_fetch_assoc($result)) { echo $row['name'] . "<br>"; } ?>
В данном примере мы получаем данные из формы, строим запрос к базе данных с учетом выбранных параметров и выводим результаты фильтрации. Не забудьте подставить свои данные для подключения к базе данных.
Таким образом, вы можете создать простой фильтр на своем веб-сайте с использованием PHP.