Обновление дочернего компонента на основе результатов поиска в функциональных компонентах react-hooks

У меня есть react-App с редуксом, использующим react-hooks функциональные компоненты, он правильно отображает список наставников в дочернем компоненте. я добавил в него окно поиска и функцию handlchange для обновления компонента списка (дочерний компонент). функция handlechange работает нормально и назначает переменную newlist в filtered внутри тела handlechange function, однако значение filtered вне функции handlechange остается неизменным, поэтому обновленная отфильтрованная переменная не назначена TutorList Component. Компонент Tutors.jsx выглядит следующим образом:

import React, { useState, useEffect } from "react";
import { useDispatch, useSelector } from 'react-redux';
import { Link, useParams, useHistory } from 'react-router-dom';
import TutorList from "./TutorList";
import * as actions from "../_actions/tutorActions";
import { TextField, Button, FormControl, } from "@material-ui/core";

const initialFieldValues = {
  search: ""
}

const Tutors = (props) => {
  const [values, setValues] = useState(initialFieldValues)

  let history = useHistory()
  const dispatch = useDispatch();
  // getting of tutorlist
  let tutor = useSelector(state => state.tutor.list);
  // sorting of tutors on date
  let tutorList = tutor.sort((a, b) => b.updatedOn.localeCompare(a.updatedOn));

  useEffect(() => {
    dispatch(actions.fetchAll())
  }, [])

  console.info("tutorList:", tutorList)

  // Variable to hold the filtered list before putting into state

  let newList = [];
  let filtered = tutorList;
  //when filter changes from '' to something filtered should be updated with newlist

  function handleChangeEvent(e) {
    const { name, value } = e.target
    const fieldValue = { [name]: value }
    setValues({
      ...values,
      ...fieldValue
    })

    // If the search bar isn't empty
    if (values.search !== "") {
      // Use .filter() to determine which items should be displayed
      // based on the search terms
      newList = tutorList.filter(item => {
        // change current item to lowercase
        const lc = item.fullName.toLowerCase();
        // change search term to lowercase
        const filter = e.target.value.toLowerCase();
        console.info("filter", filter);
        // check to see if the current list item includes the search term
        // If it does, it will be added to newList. Using lowercase eliminates
        // issues with capitalization in search terms and search content
        return lc.includes(filter);
      });
    } else {
      newList = tutorList;
    }
    console.info("newList:", newList)//shows correct list
    filtered = newList
    console.info("filtered:", filtered)//shows correct value
  }

  return (
    <div>
      <br />
      <TextField
        name = "search"
        variant = "outlined"
        label = "Search Tutor"
        paceholder = "search tutor..."
        value = {values.search}
        onChange = {handleChangeEvent}
      />

      <TutorList
        tutorList = {filtered}

      />

      <Button onClick = {() => history.goBack()}
        size = "small" variant = "contained" color = "secondary">
        back
       </Button>
    </div>
  );

}

export default Tutors;

Компонент TutorList должен отображать новый список на основе фильтра, введенного в поле поиска. кто-нибудь поможет найти обходной путь или лучшее решение. Заранее спасибо.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
110
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

создать новое состояние для

const Tutors =(props)=> {
    const [values, setValues] = useState(initialFieldValues)
    const [filtered, setFiltered] = useState(null)

внутри функции handleChangeEvent() задайте filtered значение отфильтрованного элемента:

 function handleChangeEvent(e){
       //........

      console.info("newList:",newList)//shows correct list
      //filtered=newList  <= instead of this 
      setFiltered(newList) // <= do this
      console.info("filtered:",filtered)//shows correct value
    }

Окончательный код должен выглядеть так:

import React, { useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Link, useParams, useHistory } from "react-router-dom";
import TutorList from "./TutorList";
import * as actions from "../_actions/tutorActions";
import { TextField, Button, FormControl } from "@material-ui/core";

const initialFieldValues = {
  search: "",
};

const Tutors = (props) => {
  const [values, setValues] = useState(initialFieldValues);
  const [filtered, setFiltered] = useState(null);

  let history = useHistory();
  const dispatch = useDispatch();
  // getting of tutorlist
  let tutor = useSelector((state) => state.tutor.list);
  // sorting of tutors on date
  let tutorList = tutor.sort((a, b) => b.updatedOn.localeCompare(a.updatedOn));

  useEffect(() => {
    dispatch(actions.fetchAll());
  }, []);

  console.info("tutorList:", tutorList);

  // Variable to hold the filtered list before putting into state

  let newList = [];
  let filtered = tutorList;
  //when filter changes from '' to something filtered should be updated with newlist

  function handleChangeEvent(e) {
    const { name, value } = e.target;
    const fieldValue = { [name]: value };
    setValues({
      ...values,
      ...fieldValue,
    });

    // If the search bar isn't empty
    if (values.search !== "") {
      // Use .filter() to determine which items should be displayed
      // based on the search terms
      newList = tutorList.filter((item) => {
        // change current item to lowercase
        const lc = item.fullName.toLowerCase();
        // change search term to lowercase
        const filter = e.target.value.toLowerCase();
        console.info("filter", filter);
        // check to see if the current list item includes the search term
        // If it does, it will be added to newList. Using lowercase eliminates
        // issues with capitalization in search terms and search content
        return lc.includes(filter);
      });
    } else {
      newList = tutorList;
    }
    console.info("newList:", newList); //shows correct list
    setFiltered(newList); // update filtered state
    console.info("filtered:", filtered); //shows correct value
  }

  return (
    <div>
      <br />
      <TextField
        name = "search"
        variant = "outlined"
        label = "Search Tutor"
        paceholder = "search tutor..."
        value = {values.search}
        onChange = {handleChangeEvent}
      />

      {filtered && <TutorList tutorList = {filtered} />}

      <Button
        onClick = {() => history.goBack()}
        size = "small"
        variant = "contained"
        color = "secondary"
      >
        back
      </Button>
    </div>
  );
};

export default Tutors;

Спасибо за помощь. Я пробовал это, так как я использовал разбиение на страницы в tutorList, это не работает из-за неопределенной длины null. Если я использую массив [] вместо null в const [filtered, setFiltered] = useState(null);, он не отображается в первый раз. он показывает пустой список.

Fiaz Ahmed Ranjha 13.12.2020 15:20

просто используйте условный рендеринг. {filtered && <TutorList tutorList = {filtered} />}

Ketan Ramteke 13.12.2020 15:38
Ответ принят как подходящий

Нет необходимости обновлять newList, отфильтрованный из handleChangeEvent. React так не работает. У вас не будет ререндера. Единственное, что вы должны сделать в своем handleChangeEvent, это установить значение

const [textInputValue, setTextInputValue] = useState('');
    function handleChangeEvent(e) {
        setTextInputValue(e.target.value);
    }

затем выполните всю сортировку на основе

let tutor = useSelector(state => state.tutor.list)
// and textInputValue

Также нет необходимости хранить отфильтрованные значения в состоянии.

Другие вопросы по теме