Как контролировать рендеринг компонента? React js для добавления комментария к сообщению

https://codesandbox.io/s/busy-paper-w39kvw?file=/src/components/Comments.js:141-200

const initialState = {
    comments: [
        {
            id: 1,
            username: "Kevin",
            date: "3 hours ago",
            text: "Hello",
            votes: 12,
            upvoted: false,
            downvoted: false,
            comments: []
        }

    ]
}

В моем коде комментариев у меня есть useSelector

const { comments } = useSelector(state => state.comments)

это отображает все комментарии каждый раз, когда добавляется новый комментарий

как показано здесь, с использованием инструментов разработки реакции добавить, чтобы выделить, когда компонент рендерится: https://i.gyazo.com/43a93b6d07a5802d91d9f68684e5ded5.mp4

Я пытался использовать React.memo, чтобы запомнить комментарий, но я не уверен, почему это не сработало. Есть ли способ остановить отображение всех комментариев при добавлении комментария?

Вы сопоставляете массив comments, который затем обновляете, поэтому он должен отображать весь массив при его изменении.

Monstar 23.04.2022 03:48

Что было бы идеальным способом сделать это тогда?

Bas bas 23.04.2022 04:06

Обычно вы помещаете memo/useCallback в отдельный компонент (т.е. каждый объект в комментариях).

Joel Hager 23.04.2022 05:20

Я это сделал. Я использовал React.memo для всего компонента комментариев. Тем не менее, это будет отображаться.

Bas bas 23.04.2022 05:46
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
Приложение для отслеживания бюджета на React js для начинающих
Приложение для отслеживания бюджета на React js для начинающих
Обучение на практике - это проверенная тема для достижения успеха в любой области. Если вы знаете контекст фразы "Практика делает человека...
Стоит ли использовать React в 2022 году?
Стоит ли использовать React в 2022 году?
В 2022 году мы все слышим о трендах фронтенда (React, Vue), но мы не знаем, почему мы должны использовать эти фреймворки, когда их использовать, а...
Как передать состояние или данные в react-router v6
Как передать состояние или данные в react-router v6
react-router - это лучшая библиотека для работы с маршрутизацией в reactjs. С помощью react-router вы передаете состояние или данные от одного...
2
4
43
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Когда компонент заключен в React.memo(), React визуализирует компонент и запоминает результат. Перед следующим рендерингом, если новые реквизиты одинаковы, React повторно использует запомненный результат, пропуская следующий рендеринг.

В приведенном ниже коде вы передаете функцию allComments компоненту комментария.

  const allComments = (comments, bg) => {
    const output = comments.map((comment) => {
      return (
        <Comment
          key={comment.id}
          comment={comment}
          allComments={allComments} // the function get's passed as new function object on each rerender
          bg={bg}
        />
      );
    });

    return output;
  };

what is the problem then and why this behavior?

из-за проверки равенства функций функции в javascript рассматриваются как граждане первого класса, другими словами, функции являются объектами.

function factory() {
  return (a, b) => a + b;
}
const sum1 = factory();
const sum2 = factory();
sum1(1, 2); // => 3
sum2(1, 2); // => 3
sum1 === sum2; // => false
sum1 === sum1; // => true

Функции сумма1 и сумма2 используют один и тот же источник кода, но они являются разными функциональными объектами. При сравнении их sum1 === sum2 оценивается как false. так работает Javascript.

В вашем коде новый объект функции allComments создается при каждом рендеринге с помощью реакции, который в конечном итоге передается как новая опора для React.memo(). По умолчанию React.memo() выполняет поверхностное сравнение реквизита и объектов реквизита. вот почему он вызывает новый повторный рендеринг.

Теперь мы глубоко понимаем, в чем была проблема и чем вызвано такое поведение.

Решение состоит в том, чтобы обернуть allCommentsuseCallback

Какова цель использоватьОбратный звонок? он поддерживает один экземпляр функции между рендерингами. и таким образом React.memo() будет работать.

 const allComments = useCallback((comments, bg) => {
    const output = comments.map((comment) => {
      return (
        <Comment
          key={comment.id}
          comment={comment}
          allComments={allComments}
          bg={bg}
        />
      );
    });

    return output;
  },[]);

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

Должны ли мы иметь другой тип действия для каждого обновления состояния контекста реакции?
Должен ли я использовать Redux Saga для извлечения из API, если мне не нужно хранить данные в хранилище Redux?
Как использовать навигацию Stack и Tab одновременно
При обновлении страницы значение прогресса становится равным 0 и переходит на следующую страницу React Redux
Есть ли способ настроить геттер в магазине инструментов Redux?
Неправильно ли использовать полезную нагрузку действия внутри компонента с реакцией-редукцией?
Как я могу получить ссылку на изображение, которая находится в теле моего запроса GET, с помощью React.js?
Как обновленный объект с дочерним компонентом должен отражаться на родительском компоненте
Возникли проблемы с ошибкой реакции: «Объекты недействительны в качестве дочернего элемента React. Если вы хотели отобразить коллекцию дочерних элементов, используйте вместо этого массив.
Как компоненты могут обновлять друг друга, находящиеся в разных ветках