• Как отследить конкретную ошибку и отобразить её только один раз?

    @LEXA_JA
    Тут можно сделать по разному, зависит желаемого результата.
    Если все ошибка ловить через интерсептор и вы не хотите дублировать ошибки из разных компонент, то я бы сделал буфер для ошибок по времени. Схема работы такая:
    Для каждой ошибки можно получить ключ, для одинаковых ошибок ключ должен быть одинаковым. За основу можно взять код ошибки или что-то в этом роде
    При получении ошибки получаем ключ, ключи складываем в Set. Set может быть как глобальный так и ограниченный
    Если в Set уже есть такой ключ, то ошибку игнорируем. Опционально можно не игнорировать, а обновлять существующий тост, например показать счетчик
    Если ключа нет, то показываем уведомление
    Ключи из Set пропадают по таймеру/событию, тут уже как вам удобнее, например можно использовать onClose из react-toastify.
    Ответ написан
    3 комментария
  • Как изменить state у всего списка элементов, кроме одного в React?

    @LEXA_JA
    Нужно поднять состояние в родителя:

    this.state = {
        openedServiceFormIndex: -1,
      };
    
      clickServiceCard(index) {
        this.setState(
          prevState => {
            if (index === prevState.openedServiceFormIndex) {
              return {
                openedServiceFormIndex: -1,
              }
            } else {
              return {
                openedServiceFormIndex: index,
              }
            }
          }
        );
      }
    
      render() {
      <div className="service-list">
              {serviceCards.map((card, index) => {
                return (
                  <React.Fragment key={"service-card" + index}>
                    <ServiceCard
                      opened={index === this.state.openedServiceCardIndex}
                      clickServiceCard={() => this.clickServiceCard(index)}
                      extraClass="service-list__card"
                    />
                  </React.Fragment>
                );
              })}
    </div>
      }


    И убрать из карточки

    render() {
      return (
               <div className={cn("service-card", { "--opened": this.props.opened})}>
                    <button 
                         className="service-card__btn" 
                         onClick={this.props.clickServiceCard}
                    >
                       Кнопка
                   </button>
               </div>
             )}
    }
    Ответ написан
    1 комментарий
  • Возможно ли выполнение браузерного кода на сервере?

    @LEXA_JA
    Либа для ноды по первому запросу в гугл.

    Ещё можно попробовать что-то с dataUrl

    Ну и да, хардкорный варинт, запускать браузер через puppeteer или playwright
    Ответ написан
    Комментировать
  • Как можно сделать лоадер на клике JS?

    @LEXA_JA
    async function clickHandler(event) {
            startLoading();
    
            try {
                const result = await loadSomething();
    
                success(result);
            } catch (error) {
                 fail(error)
            } finally {
                 stopLoading();
            }
        }

    Где startLoading и stopLoading показывают\скрывают лоадер, например вставляют img со спинером или переключают класс. Опционально, через fail\success можно показывать дополнительные индикаторы.
    Ответ написан
  • Как правильно настроить ESLint, Prettier в 2020 году?

    @LEXA_JA
    Похоже на то, что eslint конфиг подхватился VS Code, но не create-react-app. Если ошибки prettier не появляются в браузере, то скорее всего так и есть. Надо смотреть в сторону Продвинутой конфигурации, конкретно флаг "EXTEND_ESLINT"
    Ответ написан
    4 комментария
  • Как правильно добавить ref в кастомный input?

    @LEXA_JA
    Ответ написан
    Комментировать
  • Почему после запуска модального окна, ref возвращает null-овые объекты?

    @LEXA_JA
    Начнем с того, почему так происходит. ref срабатывает каждый раз, когда происходит рендер. Поскольку модалка использует setState, которая вызывает render, который запускает функцию в ref, в массив каждый раз попадает все больше ссылок, с каждым открытием\закрытием модалки. Иногда в ref может быть null, из-за инлайн функции Подробнее.
    Однако такой подход в принципе не правильный.
    Для управлением состоянием чекбокса, использование ref не принято. Использование ref в React в принципе нежно использовать не очень часто. Правильный подход - использование props: checked\defaultChecked и onChange Формы
    Вообще, состояние должно быть в реакте, а реакт сам применяет его на DOM, в это его суть.

    Правильный вариант - положить состояние чекбоксов в стейт, в виде массива или Set'а.
    state = {
    		values: [false, false, false], // Изначально все 3 чекбокса выключены
    	};
    
    	onToggleCheckbox = (checked, index) => {
    		this.setState(({ values: prevValues }) => {
    			const newValues = [...prevValues]; // меняем состояние нужного чекбокса по индексу
    			newValues[index] = checked;
    
    			return {
    				value: newValues,
    			};
    		});
    	};
    
    	onToggleAll = checked => {
    		this.setState(({ values }) => ({
    			values: values.map(() => checked),
    		}));
    	};

    Тогда отрисовка чекбоксов:
    <div>
        {this.props.checked.map((value, index) => (
          <input
            type="checkbox"
            checked={value}
            key={index}
            onChange={event => this.props.onToggle(event, index)}
          />
        ))}
      </div>


    Состояние чекбокса который переключает все остальный вычислимое:
    <input type="checkbox" checked={this.props.values.every(value => value)} onChange={event => this.props.onToggleAll(event.target.checked)} />
    Ответ написан
    2 комментария
  • При использовании React + redux где лучше делать логические вычисления для фильтров?

    @LEXA_JA
    В сторе лучше держать нормализованные данные, так с ними проще работать. Если дополнительно хранить в сторе отфильтрованные\отсортированные данные, то могут начаться проблемы с их синхронизацией (удалили\изменили один элемент, нужно его же обновить\удалить из отфильтрованных данных).
    Фильтрация это по сути бизнес-логика, её лучше сделать отдельно, как функцию от данных и критериев фильтрации. Критерии фильтрации и данные можно хранить в сторе. А в селекторе вызывать эту функцию, дернув данные и критерии фильтрации из стора.
    Ответ написан
    Комментировать
  • Много ли на фронтенде бизнес логики?

    @LEXA_JA
    Это сильно зависит от проекта. На каких-нибудь обычных сайтах, вроде блогов или интернет-магизинов, на фронте может вообще не быть никакой логики или самый минимум. С другой стороны существуют и полноценные веб-приложения, где логики на фронте довольно много. Особенно когда используется подход со бэком без состояния, состояние хранит клиент, и соответственно, именно клиент отвечает за бизнес логику.
    Ответ написан
  • Когда использовать useCallback, useMemo и useEffect?

    @LEXA_JA
    useEffect - это хук, который позволяет использовать сайд эффект. В классах его аналогом было использование componentDidMount, componentDidUpdate и componentWillUnmount. В нем можно делать подписки, отправлять запросы управлять анимацией и т. д.
    const [data, setData] = useState(null);
    
    useEffect(() => {
      const controller = new AbortController()
      fetchData(controller.signal).then(setData)
    
      return () => controller.abort()
    }, [fetchData, setData])


    useCallback и useMemo предназначены для оптимизации. useCallback получает на функцию и массив аргументов, и возвращает одну и туже функцию, до тех пор, пока аргументы не изменились. useMemo отличается тем, что он возвращает не саму функцию, а результат её выполнения. По большому счету они являются взаимозаменямыми.
    Таким образом, useMemo используется для сохранения результатов тяжёлых вычислений, например обработка массива.
    const data = useMemo(() => array.map(mapper).filter(predicate).reduce(reducer), [array])

    А useCallback используется, когда важна постоянность ссылок на функцию. Например, когда мы передаём ссылку в компонент, который использует React.PureComponent или React.memo, или, когда функция используется в качестве аргумента в других хуках
    const handler = useCallback(() => {
      // что-то сделать 
    }, [])
    
    useEffect(() => {
      handler(value)
      // если не использовать useCallback, эффект будет срабатывать постоянно 
    }, [handler, value])
    Ответ написан
    1 комментарий
  • Как сделать так чтобы работала обработка Отмены запроса?

    @LEXA_JA
    Как один из вариантов, можно добавить это в класс.

    Request0() {
        // this.abort()
        // можно делать это тут, если запрос должен быть только один, а можно в useEffect
        this.abortController = new AbortController()
        
        // fetch
    
        finally {
          this.abortController  = null
        }
      }
    
      abort() {
        if (this.abortController) {
          this.abortController.abort();
          this.abortController = null
        }
      }
    Ответ написан
    2 комментария
  • Узнать что другое окно закрыли?

    @LEXA_JA
    Ответ написан
    Комментировать
  • Как передать ref через props?

    @LEXA_JA
    Нужно использовать forwardRef или передать ref под другим именем.
    Ссылка на документацию

    const Input = forwardRef((props, ref) => <input ref={ref} {...props}  />)
    
    const Input = ({  inputRef, ...props }) => <input ref={inputRef} {...props} />
    Ответ написан
    Комментировать
  • Как в JSX отобразить количество элементов функции map?

    @LEXA_JA
    Длина нового массива, созданного map, будет всегда равна длине оригинального массива. Просто в тех случаях, где условие не выполняется, там будет на реактовский элемент, а false. Нужно сделать filter вместо map.
    const products = filteredProducts.filter(product => product.category === "Some, category");
    
    const count = products.length;
    
    return (
      <div className="products-list">
        <Title title="Some Title" />
        <div className="products-container">
            <p> {count} </p>
        </div>
        <div className="products-container">
          {products.map(product => (
              <ProductCard 
                 key={product.id}
                 product = {product}
               />
           ))}
         </div>
    </div>
    );
    Ответ написан
    1 комментарий
  • Как в Emmet в VS Code "сгенерировать" тег mark?

    @LEXA_JA
    Через кастомные сниппеты для emmet:

    В настройках vscode нужно указать путь к папке, где они будут лежать
    {
        "emmet.extensionsPath": "путь/к/сниппетам",
    }


    И там нужно создать фаил snippets.json, где и указываются сниппеты
    {
        "html": {
            "snippets": {
                "mark": "mark"
            }
        }
    }


    https://code.visualstudio.com/docs/editor/emmet#_u...
    Ответ написан
    1 комментарий