Как обработать состояние родительского компонента React в запомненном дочернем компоненте? - PullRequest
0 голосов
/ 05 марта 2020

Что случилось, ТАК. Я пытаюсь запомнить компонент React, но сталкиваюсь с проблемами, связанными с определением области действия. У меня есть компонент с отслеживанием состояния, который отображает список всех покемонов, которых можно добавить или удалить из списка избранного.

В настоящее время, когда я добавляю или удаляю один элемент избранного, весь список отображается повторно (что я пытаясь предотвратить). Я добавил в каждый элемент списка покемонов метод, который добавляет / удаляет покемона из списка избранного. Это работает для добавления одного покемона в список избранного, однако, когда я пытаюсь добавить второго покемона в избранное, React не распознает, что я уже добавил покемона в список избранного и, следовательно, устанавливает состояние в новый список с только одним покемоном (вторым, на которого я нажал).

Я предполагаю, что это связано с тем, что когда каждый элемент списка отображается, мой метод переключения ограничен начальным состоянием списка избранного (пустой массив), поэтому вызов setState внутри этого компонента стирает родительское состояние и перезаписывает новое состояние, содержащее только одного покемона, вместо двух что я добавил.

Итак, мне интересно, есть ли обходной путь для этого?

Компонент списка:

const List = ({ pokemonList, getSinglePokemon }) => {
  const [tabSelected, setTab] = useState('all');
  const [favorites, setFavorites] = useState([])
  const [searchParams, updateSearchParams] = useState(null)

  const addOrRemoveFavorite = (pokemon) => {
    const indexOfPokemon = favorites.indexOf(pokemon)
    const updatedList = (indexOfPokemon !== -1) ?
    [...favorites.slice(0,indexOfPokemon), ...favorites.slice(indexOfPokemon + 1)] :
    [...favorites, pokemon]
    setFavorites(updatedList)
  }

  const filteredPokemon = pokemonList.filter((p) => p.includes(searchParams))
  //prob just define the values of tabDictionary inline instead of declaring them as variables above
  const tabDictionary = { search: filteredPokemon, favorites, all: pokemonList}
  const pokeList = tabDictionary[tabSelected].map((p) => (
    <ListItem
    isFavorite={Boolean(favorites.includes(p))}
    key={p}
    getSinglePokemon={getSinglePokemon}
    name={p}
    addOrRemoveFavorite={addOrRemoveFavorite}
    />
  ))

   return (
    <div id='list' className='interface'>
      <ListHeader setTab={setTab} />
      {(() => {
        switch (tabSelected) {
        case 'search':
          return(
            <div>
            <input
            type='text' placeholder='Search Pokemon...'
            onChange={(e) => updateSearchParams(e.target.value)}
            />
            <div id='pokeList'>
              {pokeList}
              </div>
              </div>
          )
        case 'favorites':
          return(
            <div id='pokeList'>
              {pokeList}
              </div>
          )
        default:
          return(
              <div id='pokeList'>
                {pokeList}
              </div>
          )
      }})()}
    </div>
  )
}


export default List;

Компонент элемента списка:

const ListItem = ({name, getSinglePokemon, isFavorite, addOrRemoveFavorite}) => {
  return (
    <li
    className='listItem' 
    onClick={() => getSinglePokemon(name)}
    >
      {name}
      <button onClick={() => {
        addOrRemoveFavorite(name)
      }}>
      {isFavorite ? 'Remove fav' : 'Make Fav'}
      </button>
    </li>
  )
}

const areEqual = (prevProps, nextProps) => prevProps.isFavorite === nextProps.isFavorite

export default React.memo(ListItem, areEqual);
...