Магазин Redux: как подписаться на актуальные изменения в компоненте

Некоторые из моих компонентов должны быть отрисованы только один раз, так как тогда я просто хочу, чтобы они прослушивали изменения в глобальном хранилище и действовали соответственно. Но я не могу это сделать: store.subscribe и redux-watch, которые я пробовал, срабатывали только тогда, когда данные были отправлены, но не тогда, когда хранилище фактически изменилось, что означает, что соответствующая функция не может использовать this.props.bla, потому что он не обновлен еще. Есть ли какое-то решение, позволяющее узнать, когда this.props.bla действительно изменилось, без использования bla в функции рендеринга?

Пример компонента:

import React, { Component } from 'react';
import { connect } from 'react-redux';

const mapStateToProps = state => {
    return { 
         position: state.position //<== when to know for sure it changed?
    };
};

class MyComp extends Component {
    constructor(props) {
        super(props);    
        this.state = {
            number: 0
        };
        store.subscribe(() => {
            const currentState = store.getState();
            // even if I have the updated value here in currentState, there are not guarantees this.props.position already changed.
        });
    }
    calculate = ()=>{
       // Do some calculation with this.props.position and change the number.
    }
    render(){
       return <div>{this.state.number}</div>;
   }
}

export default connect(mapStateToProps)(MyComp);

Вы можете подписаться на изменения в магазине Redux, подписавшись на магазин. Не используйте store.subscribe напрямую. Используйте connect HOC или useSelector реакцию, чтобы подключиться к прослушиванию конкретных изменений.

Drew Reese 24.12.2020 03:15

Извините, но Redux - это такая боль .... Только что перешел на React Query, и мне это нравится. Я могу буквально перейти на страницу, показывающую 4 записи базы данных, перейти к моему инструменту базы данных и удалить запись, а затем, когда я снова нажму на окно браузера, оно обновится. Вы также можете отменить любые существующие запросы, заставив React Query снова получить данные.

Tony Drummond 24.12.2020 03:38

@DrewReese Я уже использую соединение, но я не знаю, как прослушивать изменения, если я не добавляю реквизиты в функцию рендеринга. Можете ли вы привести пример такого компонента (может быть, вы создадите ответ?) Спасибо!

mimic 24.12.2020 03:41

@TonyDrummond Спасибо за совет! Я тоже думаю использовать что-то другое. Позволяет ли Reac Query иметь центральное хранилище, такое как хранилище избыточности. Мне нужно несколько компонентов, чтобы использовать какой-то глобальный источник.

mimic 24.12.2020 03:42

@mimic - я только что сделал это видео для кого-то сегодня, который кратко просматривает его. Я новый разработчик (3 месяца опыта работы со стеком MERN) и смог преобразовать все свое приложение, исключив 1500 строк действий Redux, констант, редьюсеров и других BS. Вот: youtu.be/rb7ZDj-0NWU

Tony Drummond 24.12.2020 03:44

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

Drew Reese 24.12.2020 03:56

@TonyDrummond Redux (и, соответственно, react-redux) в порядке, хотя и немного многословен. Если шаблонность старого react-redux для вас слишком велика, я предлагаю вам проверить redux-toolkit от той же команды, которая принесла вам react-redux. По сути, это еще один уровень абстракции по сравнению с react-redux, который обрабатывает «шаблонный» код за вас. Кроме того, он инкапсулирует логику редуктора, поэтому вам не нужно беспокоиться об изменчивости состояния.

Drew Reese 24.12.2020 04:00

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

mimic 24.12.2020 04:01

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

Drew Reese 24.12.2020 04:02

@DrewReese спасибо, но после использования React Query я никогда не вернусь к Redux :). Запрос React обрабатывает весь магазин — мне не пришлось ничего настраивать.

Tony Drummond 24.12.2020 04:03

Вы читали редукс-документы для магазина , подписывайтесь . «Добавляет прослушиватель изменений. Он будет вызываться каждый раз, когда отправляется действие, и некоторая часть дерева состояний потенциально может измениться. Затем вы можете вызвать getState(), чтобы прочитать текущее дерево состояний внутри обратного вызова». Вы пытались получить текущее состояние в обратном вызове?

Drew Reese 24.12.2020 04:13

@DrewReese Я не спрашиваю, как увидеть значение внутри обратного вызова. Мне нужен надежный способ прочитать изменения ПОСЛЕ их выполнения, а не в обратном вызове. Рабочий процесс таков: 1) вносятся изменения в хранилище 2) компонент знает об этом и 3) вызывает соответствующую функцию 4) которая считывает измененные данные из хранилища. Функция рендеринга имеет прямое действие — она перерисовывает мой компонент. У компонента есть функция рендеринга, но он работает в основном с другими данными, которые не помещаются в функцию рендеринга. Что мне нужно, так это надежный способ узнать об изменениях, сделанных в магазине.

mimic 24.12.2020 05:39

@DrewReese Я добавил пример компонента.

mimic 24.12.2020 05:52

Итак, вы просто хотите знать, когда обновляется значение state.position/props.position? Внедрите componentDidUpdate метод жизненного цикла, сравните prevProps.position !== this.props.position и сделайте то, что вам нужно.

Drew Reese 24.12.2020 07:18

@DrewReese, вы правы, я просто хочу знать, когда this.props.value изменилось, позвольте мне попробовать это решение.

mimic 24.12.2020 20:26

@DrewReese Это сработало!! Не могли бы вы добавить свой комментарий в качестве ответа, я отмечу его как решение. Спасибо!

mimic 27.12.2020 00:33
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
16
889
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Если вы хотите «отреагировать» на конкретное обновление значения реквизита, вам следует реализовать метод жизненного цикла componentDidUpdate. В вашем случае, если вам нужно знать, когда обновилось введенное значение реквизита position, добавьте условие для сравнения предыдущего значения реквизита position с текущим значением реквизита position.

componentDidUpdate(prevProps) {
  if (prevProps.position !== this.props.position) {
    // position value updated!
  }
}

У меня есть другая проблема - по какой-то причине, когда значение хранилища избыточности изменяется, мой render() вызывается, но не componentDidUpdate(), и я не могу понять, почему. Есть идеи? Спасибо!

mimic 26.02.2021 18:44

@mimic Я не могу представить себе сценарий, в котором render можно было бы вызвать при обновлении DOM и каким-то образом componentDidUpdate не вызвать. Не стесняйтесь задавать новый вопрос о SO и пинговать меня здесь со ссылкой на него, я могу взглянуть, когда у меня будет минутка. Как минимум, он будет более заметен, и вы сможете быстрее привлечь к нему внимание.

Drew Reese 26.02.2021 18:52

Спасибо, Дрю! На самом деле я обнаружил, что монтирую компонент вместо его обновления, ха-ха, поэтому он не вызывался, а был вызван componentDidMount() :)

mimic 26.02.2021 19:50

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