Ответы пользователя по тегу React
  • Как протестировать enzyme мини компонент?

    @slide13
    frontend/web-developer
    Через find
    const wrapper = shallow(<Boz/>);
    expect(wrapper.find(MuiBoz)).to.have.lengthOf(1);

    Возможно, потребуется пропы замокать еще через wrapper.setProps
    Ответ написан
    Комментировать
  • Почему так работает useState?

    @slide13
    frontend/web-developer
    Так работает из-за StrictMode в реакте, потому что в этом режиме на этапе разработки Реакт делает дополнительную проверку и делает вызовы некоторых методов дважды (собственно, это и видно в консоли):

    Строгий режим не способен автоматически обнаруживать побочные эффекты, но помогает их отследить, сделав более детерминированными. Такое поведение достигается путём двойного вызова следующих методов:
    1. Методы constructor, render, и shouldComponentUpdate классового компонента
    2. Статический метод классового компонента getDerivedStateFromProps
    3. Тело функционального компонента
    4. Функции обновления (первый аргумент setState)
    5. Функции, переданные в useState, useMemo, или useReducer


    В продакшен сборке будет все ок, можно проверить убрав обертку StrictMode, тогда в теле компонента и в useEffect значение test будет одинаковым и вызываться console.log("component", test); будет только один раз при вводе в инпут.
    Ответ написан
    1 комментарий
  • Как подключить стили в nextjs?

    @slide13
    frontend/web-developer
    Я nextjs не использовал, но судя по ошибке он говорит, что глобальные css файлы можно хранить только в одном месте, а если требуется инкапсулировать css по компонентам, то нужно использовать css модули.
    Т.е. по идее css модули должны работать по дефолту, следовательно переименовываем файл в Footer.module.scss и также его и импортируем.
    Ответ написан
    Комментировать
  • Как получить значение switch в vkui?

    @slide13
    frontend/web-developer
    Также, как и с обычным input type="checkbox" в реакт - либо передаете значение checked в компонент сами и функцию onChange для изменения этого значения, либо через ref, что в данном случае проще будет

    Документация
    Ответ написан
    Комментировать
  • Почему возвращает Failed to fetch?

    @slide13
    frontend/web-developer
    Подозреваю, что проблема в https и запрос на http://localhost:5000/add-user/ будет работать. Для https нужен ssl сертификат, а в коде сервера не вижу создания https сервера.
    Ответ написан
    Комментировать
  • Как в react передать функции новое состояние?

    @slide13
    frontend/web-developer
    Вариант по сути только один, наверное - сохранять состояние в ref.

    Но все равно придется обновлять ref в useEffect:
    useEffect(() => {
        ref.current = status;
      }, [status]);

    Из ref уже читать статус в вашей функции getStatus, где ref.current будет содержать всегда последнее значение status.
    Ответ написан
  • Как считать данные с ссылки в форму?

    @slide13
    frontend/web-developer
    Если IE не нужен, то можно через URLSearchParams

    let url = 'email=user%40mail.com&phone=380989035745&date=19911225&offer=1&lang=ua&country=ua'
    console.log([...new URLSearchParams(url).entries()].reduce((query, [key, value]) => Object.assign(query, {[key]: value}), {}))
    Ответ написан
    Комментировать
  • Как работает функция componentDidUpdate?

    @slide13
    frontend/web-developer
    1. Вы ввели "1", нажали кнопку: у родителя меняется состояние на {value: "1"}, Child обновляется первый раз
    2. componentDidUpdate не срабатывает при первом рендере, поэтому в Child просто выводится Hello!
    3. В инпуте все еще "1", вы нажали второй раз кнопку. Снова вызывается setState с {value: "1"}, но каждый вызов setState приводит к перерендеру компонента, поэтому после второго клика происходит обновление родителя и вслед за ним потомка
    4. На второй перерендер у Child срабатывает componentDidUpdate, и т.к. состояние в потомке не определено, т.е. по дефолту равно null, то срабатывает условие в if в componentDidUpdate
    5. Child обновляет свой state и записывает туда {value: "1"}, после снова обновляется, но т.к. теперь предыдущий state был равен null, а текущий {value: "1"}, то условие if в componentDidUpdate уже не выполняется
    6. Добавляете в инпуте цифру "2", нажимаете кнопку. Родитель меняет состояние на {value: "12"} и обновляется вместе с потомком
    7. И дальше ответ на ваш вопрос: у Child снова после обновления срабатывает componentDidUpdate. При этом предыдущее значение у него в state осталось то, что было записано в пункте 5 и текущее тоже равно этому же значению, т.е. в этом случае опять сработает if и в Child изменится состояние на {value: "12"}
    8. Child снова обновляется после изменения своего состояния, срабатывает componentDidUpdate, предыдущее значение состояния value выводит "1", а текущее уже "12" так что if снова не срабатывает


    Надеюсь понятно написал ) Не понятно только зачем вам в Child нужно состояние, которое дублирует пропы, так делать не надо
    Ответ написан
    3 комментария
  • Как сделать сброс стилей в styled components?

    @slide13
    frontend/web-developer
    Либо вытаскивай нужные стили для сброса и указывай в createGlobalStyle, либо есть библиотека styled-normalize, просто компонент выше приложения вставляется:

    import { Normalize } from 'styled-normalize'
    ...
    <Normalize />
    <App />

    Можно и через createGlobalStyle вставить, все в доке есть по styled-normalize
    Аналогично для reset css
    Ответ написан
    1 комментарий
  • Стоит ли использовать хуки вроде useState когда уже управляешь состоянием с помощью Redux?

    @slide13
    frontend/web-developer
    Про редакс уже все сказали, часто есть необходимость использовать useState при наличии redux и это нормально.

    Про replace. Т.к. в replace у строки вторым параметром можно передать функцию, то здесь явно можно этим и воспользоваться:
    сделать объект, где ключом была бы подстрока из совпадения, а значением - то, на что ее нужно заменить и потом по совпадению подставлять нужное значение из объекта, примерно так:
    let matches = {
      ",": "",
      "в": "В",
      "с": "С",
      " г.": ""
    }
    
    .replace(/с|в|\sг./g, (match) => matches[match])

    Но из того, что я вижу, проще взять библиотеку dayjs и спокойно форматировать даты, 2KB вряд ли стоят времени на написание своих реализаций форматирования дат

    Далее, естественно, не надо хранить функции в редаксе. Различные доп. функции лучше выносить в отдельную папку и разбивать по типам, например, для работы с датами, для форматирования чисел и т.д. и импортировать в нужные компоненты непосредственно оттуда.
    Это полезно, т.к. никто не знает, когда и кому она пригодится снова, а тем более если это большой проект. Написав ее где-то у себя в компонентах ее могут не найти и создать копию где-то еще. Также ее придется тестировать, импортировать утилиты для тестов проще из одного места, чем искать по компонентам, а утилиты все равно придется тестить отдельно от ui.
    Ответ написан
    Комментировать
  • Настроить страницу (pagination material ui)?

    @slide13
    frontend/web-developer
    Сколько вам нужно выводить на странице статей - на это число и делите общее кол-во статей. articlesTotalCount / MAX_ARTICLES_ON_PAGE, ну и округлить не забудьте на всякий.

    Только у вас интересный бэк какой-то - он на любой offset выдает статьи даже за пределом возвращаемого максимального кол-ва, я 200 000 пробовал и статьи там есть )
    Ответ написан
  • Как стилизовать Autocomplete в React Material UI?

    @slide13
    frontend/web-developer
    У Select есть проп renderValue, позволяющий выводить кастомное значение в поле селекта, т.е. как раз то, что вам нужно.

    Вот пример: https://codesandbox.io/s/material-demo-zegwq
    Ответ написан
    Комментировать
  • Как сделать плавное удаление элемента из массива с react-spring?

    @slide13
    frontend/web-developer
    Например, так:
    const transBoxes = useTransition(boxes, boxes => boxes, {
        from: { opacity: 0, width: 100, transform: "translateY(-100px)" },
        enter: { opacity: 1, transform: "translateY(0px)" },
        leave: [{ transform: "translateY(100px)", opacity: 0 }, { width: 0 }],
        config: {
          duration: 750
        }
      });
    Ответ написан
    1 комментарий
  • Кто то может объяснить в чем разница между React-router-dom and React-router-redux? Можно ли их использовать одновременно?

    @slide13
    frontend/web-developer
    Вместо react-router-redux сейчас используется connected-react-router. Разница в том, что пакет react-router-dom как раз и предоставляет роутинг (если кратко, рендерит различные компоненты в зависимости от текущего пути), а connected-react-router выносит стейт роутера в redux, позволяя изменять путь с помощью асинхронных экшенов. Т.е. отсюда следует, что connected-react-router используется только вместе с react-router-dom, но необходим только в некоторых случаях.
    Ответ написан
    Комментировать
  • Функциональный компонент не перерендеривается, в чём проблема?

    @slide13
    frontend/web-developer
    Артур Галяев, у вас значение date не меняется, т.к. объект moment мутабельный и при манипуляциях с датой не меняет ссылку на исходный объект, date.add(1, 'month') это тот же самый объект момент. Если вам нужно в стейте хранить именно весь объект moment либо добавьте .clone() в конце, чтобы клонировать объект момент:
    date.add(1, 'month').clone()
    либо вместо moment используйте иммутабельную библиотеку для работы с датами, например, dayjs
    Я, в принципе, не советую moment использовать, когда есть более легковесные аналоги (moment - 70.4
    kB, dayjs - 2.8kB)
    Ответ написан
    1 комментарий
  • Как правильно прописать Redirect в react-router-dom?

    @slide13
    frontend/web-developer
    Почему у вас Suspense внутри Switch? Он должен быть выше и тогда все заработает как нужно, т.е. порядок такой:
    <Suspense fallback={<div>loading...</div>}>
      <Switch>
        <Redirect from="/" to="/documents" exact />
    Ответ написан
    1 комментарий
  • Formik не обновляет форму, как исправить?

    @slide13
    frontend/web-developer
    Я так понимаю у вас меняется initialValues при смене урла? Тогда необходимо добавить настройку enableReinitialize: true, чтобы форма обновлялась при смене initialValues
    Ответ написан
    Комментировать
  • Как изменить названия месяцев в material-ui pickers DatePicker?

    @slide13
    frontend/web-developer
    Чтобы все названия месяцев при использовании date-fns были в именительном падеже необходимо убрать из локали форматированные названия месяцев (т.е. formattingMonthValues).

    Для этого либо:
    1. Создаем отдельный файл с локалью, копируем в него все из имеющейся в date-fns ru локали. С помощью buildLocalizeFn перезаписываем месяцы и импортируем везде, где нужно этот файл вместо локали из date-fns/locale/ru.

    Код для измененной ru локали без форматированных месяцев:

    import formatDistance from "date-fns/locale/ru/_lib/formatDistance";
    import formatRelative from "date-fns/locale/ru/_lib/formatRelative";
    import localize from "date-fns/locale/ru/_lib/localize";
    import match from "date-fns/locale/ru/_lib/match";
    import formatLong from "date-fns/locale/ru/_lib/formatLong";
    import buildLocalizeFn from 'date-fns/locale/_lib/buildLocalizeFn'
    
    const monthValues = {
      narrow: ["Я", "Ф", "М", "А", "М", "И", "И", "А", "С", "О", "Н", "Д"],
      abbreviated: [
        "янв.",
        "фев.",
        "март",
        "апр.",
        "май",
        "июнь",
        "июль",
        "авг.",
        "сент.",
        "окт.",
        "нояб.",
        "дек."
      ],
      wide: [
        "январь",
        "февраль",
        "март",
        "апрель",
        "май",
        "июнь",
        "июль",
        "август",
        "сентябрь",
        "октябрь",
        "ноябрь",
        "декабрь"
      ]
    };
    
    const ruLocale = {
      formatDistance,
      formatLong,
      formatRelative,
      localize: {
        ...localize,
        month: buildLocalizeFn({
          values: monthValues,
          defaultWidth: "wide",
          defaultFormattingWidth: "wide"
        })
      },
      match,
      options: {
        weekStartsOn: 1,
        firstWeekContainsDate: 1
      }
    };
    
    export default ruLocale;


    2. Перезаписываем нужные месяцы в имеющейся локали напрямую после импорта

    import ru from "date-fns/locale/ru";
    import buildLocalizeFn from 'date-fns/locale/_lib/buildLocalizeFn'
      
      const monthValues = {
        narrow: ["Я", "Ф", "М", "А", "М", "И", "И", "А", "С", "О", "Н", "Д"],
        abbreviated: [
          "янв.",
          "фев.",
          "март",
          "апр.",
          "май",
          "июнь",
          "июль",
          "авг.",
          "сент.",
          "окт.",
          "нояб.",
          "дек."
        ],
        wide: [
          "январь",
          "февраль",
          "март",
          "апрель",
          "май",
          "июнь",
          "июль",
          "август",
          "сентябрь",
          "октябрь",
          "ноябрь",
          "декабрь"
        ]
      };
    
      ru.localize.month = buildLocalizeFn({
        values: monthValues,
        defaultWidth: 'wide',
        defaultFormattingWidth: 'wide'
      })
    Ответ написан
    1 комментарий
  • Как проверять типы данных значений передаваемых в функцию (prop-types)?

    @slide13
    frontend/web-developer
    Встроенной проверки параметров функций в prop types нет, но можно написать кастомный валидатор:

    customProp: function(props, propName, componentName) {
        if (!/matchme/.test(props[propName])) {
          return new Error(
            'Проп `' + propName + '` компонента' +
            ' `' + componentName + '` имеет неправильное значение'
          );
        }
      }

    Документация тут
    Ответ написан
    Комментировать
  • Зачем хранить state в localStorage c помощью react-persist?

    @slide13
    frontend/web-developer
    Скорее всего имеется в виду redux-persist? Он нужен, чтобы, например, после перезагрузки вашего приложения состояние возвращалось к тому, которое было до перезагрузки, что экономит время на инициализацию, запросы данных, которые ранее уже были загружены и т.д.
    Не обязательно хранить состояние в localStorage, для этого рекомендуется использовать библиотеку localForage, которая позволяет использовать IndexedDB или WebSQL
    Ответ написан
    Комментировать