Состояние реакции изменяется, но компонент не перерисовывается

Любая помощь будет оценена по достоинству. Я получаю свои данные из внешней базы данных и подаю их с наблюдаемыми. Компонент обновляется при изменении состояния игроков, но не обновляется при изменении состояния монстров.

Я вижу, что состояние правильное и заполнено ненулевыми данными, отлаживая компонент с помощью инструментов разработчика React. Если я заставлю игроков обновиться снова, он правильно перерисует монстров, но setMonsters сам по себе не вызывает повторный рендеринг.

export default () => {
  const [players, setPlayers] = useState({})
  const [monsters, setMonsters] = useState({})

  useEffect(() => {
    const playersSub = players$.subscribe(setPlayers)
    const monstersSub = monsters$.subscribe(x => {
      console.log('should be re-rendering...')
      setMonsters(x)
    })

    return () => {
      playersSub.unsubscribe()
      monstersSub.unsubscribe()
    }
  }, [])

  return (
    <Section style={{ backgroundColor: medium, borderRadius: '.5rem', flex: '1 0 0' }}>
      {Object.entries(players).map(([key, x], i) => {
        if (!x.investigator) return <div key={key} />
        return <Player player={x} key={key} />
      })}
      {Object.entries(monsters).map(([key, x]) => {
        console.log('what is going on?')
        return <Monster monster={x} key={key} />
      })}
    </Section>
  )
}

Как ни странно, когда я обновляю страницу, она обновляется и показывает правильный рендер всего за долю секунды до закрытия.

РЕДАКТИРОВАТЬ

Хорошо, я «исправил» это, но я все же хотел бы знать, что вызывает проблему, если кто-нибудь может пролить свет на эту проблему для меня.

Решение для меня столь же странное, как и проблема, и я считаю, что хорошо знаком с React и RxJS.

Я изменил подписку на это.

  useEffect(() => {
    const playersSub = players$.subscribe(setPlayers)
    const monstersSub = monsters$.subscribe(x => {
      setMonsters({ ...x })
    })

    return () => {
      playersSub.unsubscribe()
      monstersSub.unsubscribe()
    }
  }, [])

И теперь он работает, как задумано. Это не похоже на то, что это должно что-то делать.

Предостережение: я не знаком с rxjs. Я считаю, что React выполняет повторный рендеринг, когда обнаруживает изменение состояния, которое он принимает на основе ссылочного равенства. Если x всегда указывает на один и тот же массив/объект, он не узнает, что он изменился. Используя оператор распространения, вы создали новый массив/объект, и он знает, что его необходимо повторно отобразить.

Nikki9696 06.04.2022 21:03

Этот человек объясняет лучше, чем я =) blog.bitsrc.io/…

Nikki9696 06.04.2022 21:07

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

Aaron Gayle 06.04.2022 21:36
Получение данных из формы с помощью JavaScript - краткое руководство
Получение данных из формы с помощью JavaScript - краткое руководство
Получить данные из формы с помощью JS очень просто: вы запрашиваете элемент формы, передаете его конструктору new FormData() и, наконец, получаете...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Сравнение структур данных: Массивы и объекты в Javascript
Сравнение структур данных: Массивы и объекты в Javascript
Итак, вы изучили основы JavaScript и хотите перейти к изучению структур данных. Мотивация для изучения/понимания Структур данных может быть разной,...
Создание собственной системы электронной коммерции на базе Keystone.js - настройка среды и базовые модели
Создание собственной системы электронной коммерции на базе Keystone.js - настройка среды и базовые модели
Прошлая статья была первой из цикла статей о создании системы электронной коммерции с использованием Keystone.js, и она была посвящена главным образом...
Приложение для отслеживания бюджета на React js для начинающих
Приложение для отслеживания бюджета на React js для начинающих
Обучение на практике - это проверенная тема для достижения успеха в любой области. Если вы знаете контекст фразы "Практика делает человека...
0
3
33
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

React использует равенство Объект.is() (ссылочное), чтобы определить, было ли обновлено состояние. Мы не должны напрямую изменять состояние, так как если вы отправляете ему ту же ссылку, оно просто не узнает.

Вы можете либо отправить совершенно новую копию, как вы делали это в своей рабочей версии, либо использовать синтаксис, который использует функцию обновления для установки состояния из текущего состояния.

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