Ответы пользователя по тегу React
  • Должен ли useSelector так часто обновляться?

    Alexandroppolus
    @Alexandroppolus
    кодир
    Одно из двух: либо слишком часто обновляется стор, либо ты поймал бесконечный ререндер.
    Хотя, кстати, возможен комбинированный вариант - вызов эффекта на каждом ререндере, обновление стора в эффекте.

    В общем, без кода непонятно.
    Ответ написан
  • Передача данных?

    Alexandroppolus
    @Alexandroppolus
    кодир
    у тебя act.violation_type равен undefined.
    такие дела.
    Ответ написан
    4 комментария
  • Чем лучше инициализировать переменные, дефолтными значениями или null?

    Alexandroppolus
    @Alexandroppolus
    кодир
    Если "пустое" значение совсем валидно, то лучше его. Если совсем невалидно, то null.
    Разумеется, есть и промежуточные варианты, когда это значание - объект, и некоторые поля можно использовать, а некоторые нет. Тут по ситуации, исходя из того, как удобнее делать проверки.

    C null можно ещё немного переписать код так:

    return value == null ? <EmptyComponent ../> : <RealComponent value={value} />


    тогда внутри RealComponent у тебя гарантированно правильное значение, с которым можно спокойно работать.
    Ответ написан
    Комментировать
  • В каких случаях используют useEffect без второго аргумента в виде массива?

    Alexandroppolus
    @Alexandroppolus
    кодир
    использовал для кейса, когда есть реф и у этого рефа current мог меняться во время жизни компонента.

    вкратце:
    const ref = useRef<HTMLDivElement>(null);
    const prevRef = useRef<HTMLDivElement>(null);
    
    useEffect(() => {
        if (ref.current === prevRef.current) { return; }
        prevRef.current = ref.current;
    
        // реф поменялся, что-то делаем
    });


    по факту я здесь делаю то же самое, что происходит в депенденсах, но депенденсы непригодны:
    1) [ref] - бесполезно, будет один и тот же, эффект не перевызовется
    2) [ref.current] - бесполезно, реф меняется после фазы рендера.
    Ответ написан
  • Как вызвать кастомный hook внутри провайдера в тесте?

    Alexandroppolus
    @Alexandroppolus
    кодир
    У функции renderHook есть второй параметр-обьект, там можно задать всякие настройки. Тебе надо в поле wrapper воткнуть компонент, в котором есть провайдер этого контекста.
    Ответ написан
    Комментировать
  • Как запретить рендер части компоненты?

    Alexandroppolus
    @Alexandroppolus
    кодир
    Component должен быть React.memo

    как вариант, можно написать
    const componentElement = <Component/>;
    
    const Parent = () => {
    
      return (
        <section>
          {componentElement}
        </section>
      );
    };


    почему этот странный и немного костыльный вариант не вызывает ререндер чилда при ререндере парента? Потому что так во время ререндера парента не создается новый элемент (переиспользуется старый объект componentElement). А ререндер чилда из-за ререндера парента возможен только при новом элементе. Такие дела.
    Ответ написан
  • Нужно ли устанавливать на ПК node.js для разработки приложений на React и React Native?

    Alexandroppolus
    @Alexandroppolus
    кодир
    Весь (за мелкими исключениями) инструментарий для фронта работает на node.js. Так что без вариантов.
    Ответ написан
    Комментировать
  • Как решить проблему с рендером в тестах с асинхронным кодом?

    Alexandroppolus
    @Alexandroppolus
    кодир
    Самый православный вариант - в AppStoreProvider для тестов подставлять вместо реального DetailClipStore заглушку, которая реализует тот же интерфейс. У тебя ведь тест на реакт-компонент? Вот и незачем туда тащить DetailClipStore (попутно тестируя и его тоже). На него лучше написать отдельный тест, в котором проверить чисто логику.
    Ответ написан
    Комментировать
  • Какой правильный порядок будет в консоли?

    Alexandroppolus
    @Alexandroppolus
    кодир
    почему дальше у нас сначала идет лог из рефа ребенка, а только потом из рефа родителя - непонятно

    назначение рефов происходит на том же этапе, что и выполнение колбэка в useLayoutEffect: синхронно сразу после того, как сформируется дерево виртуального дома, и по нему будет обновлено дерево реального дома. Все перечисленное делается в одном синхронном куске кода, без микротасков и т.д. Разумеется, до этапа отрисовки на экране.
    Почему снизу вверх, то есть от чилдов к парентам? Значения рефов могут использоваться в колбэках useLayoutEffect, значит они к этому моменту должны быть готовы. Т.е. чилд должен успеть назначить реф до того, как парент попробует к нему обратиться. Распространение данных в обратную сторону, в комплект к распространению в прямую (через пропсы). Это одна из причин, могут быть и другие.

    Эффекты useEffect срабатывают после отрисовки на экране, т.е. в отдельном таске. Для единообразия они тоже срабатывают в порядке от чилдов к парентам.

    Указанный порядок имеет свои минусы, например https://habr.com/ru/articles/574536/ , но в целом плюсы перевешивают.

    Надо заметить, что и функции очистки для useEffect и useLayoutEffect тоже вызываются сначала на чилдах, что правильно со всех сторон.
    Ответ написан
    Комментировать
  • В каких ситуациях надо использовать хук useImperativeHandle?

    Alexandroppolus
    @Alexandroppolus
    кодир
    Это может понадобиться, если в твоем компоненте используется какая-нибудь хрень, которой удобно управлять не через изменение пропсов (стандартный react-way), а через вызовы функций. Ну вот тот же пресловутый инпут или текстареа - у него есть штуки, которые не отобразились на пропсы, например выделение текста.

    Соответственно, чтобы вызывать функции, нужен экземпляр - что-то вроде viewModel для твоего компонента. И тут два пути: либо ты вручную создаешь этот объект, просовываешь через проп, и компонент к нему "подключается", либо компонент сам создает сей объект и возвращает тебе, уже с помощью рефа. Вот useImperativeHandle реализует второй способ. При размонтировании, реф обнуляется, компонент "заметает следы".

    Пример из более-менее известного - библиотека Формик
    https://github.com/jaredpalmer/formik/blob/main/pa...
    formikbag - тот самый "объект с методами". Он создается через хук useFormik, но конкретно здесь компонент Formik сам это сделал и отдал тебе
    Ответ написан
    Комментировать
  • Как избежать дублирования повторяющихся свойств и значений в объектах массива?

    Alexandroppolus
    @Alexandroppolus
    кодир
    эту странную хотелку можно сделать через прототипы
    const commonData = {
        title: "Title",
        description: "Description",
    };
    
    const arr = [
        {value: 'Value1'},
        {value: 'Value2'}
    ].map((obj) => Object.setPrototypeOf(obj, commonData));
    
    console.log(arr[0].value); // Value1
    console.log(arr[0].title); // Title


    но если твой массив пришел с бэка и был распарсен, то уже нет смысла мутить
    Ответ написан
  • Как устранить ошибку Cannot read properties of undefined (reading 'preventDefault')?

    Alexandroppolus
    @Alexandroppolus
    кодир
    Судя по всему, компонент Form, не представленный в вопросе, вызывает onSubmit без каких-либо параметров.
    Ответ написан
    Комментировать
  • Почему показывает что данные контекста пустые, хотя это не так?

    Alexandroppolus
    @Alexandroppolus
    кодир
    Скорее всего, этот твой console.log(like) вызывается до того, как лайчинские загружены. Потому в консоли рисуется Array(0). Далее ты кликаешь на треугольник, но к этому моменту данные уже приходят и потому видны. "Array(0)" не меняется, остаётся как есть.

    Проблема твоего стора Like в том, что это нихрена не стор. Он не уведомляет никого об изменении своих данных. Компоненты не перерисовываются. Проще всего здесь использовать mobx, тогда достаточно будет добавить пару строчек в классе Like. Ну, или какой-то иной стейт-манагер.
    Ответ написан
    2 комментария
  • Почему из-за Suspense в React.js(ts) не срабатывает onLoadedData на видео?

    Alexandroppolus
    @Alexandroppolus
    кодир
    Самое странное то, что на продакшн версии обработчик корректно работает

    почти наверняка из-за React.StrictMode - там двойное монтирование, и вообще всё двойное. Попробуй его убрать.
    Ответ написан
    3 комментария
  • Почему eslint предлагает внедрить в хук странную зависимость?

    Alexandroppolus
    @Alexandroppolus
    кодир
    setChatUsers(x=>setUserOnline(lastChatMessage, x));
    setChatUsers(x=>setUserOffline(lastChatMessage, x));
    Ответ написан
    Комментировать
  • Как избежать перерисовки компонента?

    Alexandroppolus
    @Alexandroppolus
    кодир
    если их будет 100 тысяч

    то надо просто взять react-window и... использовать по назначению

    а так - вышеупомянутый key, React.memo, и прочая..
    Ответ написан
    Комментировать
  • Ошибка в React.js "The `style` prop expects a mapping from style properties to values, not a string..?

    Alexandroppolus
    @Alexandroppolus
    кодир
    В проп style надо передавать объект, а ты зачем-то ставишь туда строку.
    Ответ написан
    Комментировать
  • Почему state нужно передавать компонентам через connect?

    Alexandroppolus
    @Alexandroppolus
    кодир
    Вообще говоря, connect теперь безнадежно устарел и рекомендуется использовать хуки. В частности, useSelector позволяет прочитать данные и ещё и подписаться на их изменение. Причем, изменение не всего стейта, а только этого куска, который мы селектим. Старый добрый connect делал то же самое.

    Так же ты можешь затянуть весь стор (не стейт) с помощью useStore и в моменте посмотреть его текущий стейт. Но это без подписки на изменение.

    Сам по себе стор хранится в провайдере контекста, и к нему обращаются все упомянутые хуки. По факту - тот же DI, что с архитектурной т.з. лучше импорта.

    Но надо заметить, что это уже не redux, а react-redux, т.е. отдельный пакет, хоть и официальный. Ты можешь чисто ради прикола и в учебных целях поюзать redux напрямую - например, для постижения хука useSyncExternalStore.
    Ответ написан
    Комментировать
  • Как обновлять стейт с бесконечно вложенным списом?

    Alexandroppolus
    @Alexandroppolus
    кодир
    this.comments = this.comments.map(...)

    этот map обходит только верхний уровень комментов. Соответственно, если id принадлежит какому-то вложенному комменту, он просто не найдется.

    Надо перебирать рекурсивно все комменты, чтобы отыскать по id. А как найдешь, просто выставить в нем поле children, и завершить рекурсию
    foundComment.children = data;

    эта твоя замена с помощью map - очень дурацкая идея, много лишних перерисовок, не "mobx-way"

    для полноты картины отметим ещё, что в комплект к RecursiveComponent надо бы отдельный компонент для комментария, и оба эти компонента обернуть в observer. Тогда будет всё как задумано великим чуваком - автором mobx.

    а если комментов совсем дохрена (например, тысячи), то стоит подумать об их быстром поиске с помощью Map
    Ответ написан