Описване на props с PropTypes идващи от HOC от външна библиотека

Fakeheal

Super Moderator
Използвам i18next (и пакета им за reactjs) и имам class component, който ползва i18next - withTranslation:

JavaScript:
import React, { Component } from 'react';
import { withTranslation } from 'react-i18next';

class Home extends Component {
  constructor(props) {
    super(props);
    // some default values are set here
  }

  componentDidMount() {
    // some http requests are happening here
  }

  render() {
    const { t } = this.props;
    return (
      <h1>{t('pageHome:title')}</h1>
    );
  }
}

export default withTranslation()(Home);

Също така съм си сложила linter-a за js & react на airbnb и от него получавам грешка:

ESLint: t is missing in props validation (react/prop-types)

Защото t идва от HOC: withTranslation()

Единствения начин, по който мога да я премахна е с:

Код:
Home.propTypes = {
  t: PropTypes.func.isRequired,
};

Но не съм сигурна, че това е правилния начин. Няма ли някак си linter-a да разбере, че prop-a идва от Higher Order Component-a от package-a
 
Последно редактирано:
Имаш и други варианти. Зависи от целта, която искаш да постигнеш.

Ако използваш prop types и на други места, то тогава единия вариант е начина, по който ти си подтиснала грешката.

Ако не искаш да използваш prop types, но искаш да подтиснеш линтера е, то можеш да игнорираш проверката с коментар:

Код:
/* eslint-disable-next-line */
const { t } = this.props;

Код:
const { t } = this.props; // eslint-disable-line

или https://eslint.org/docs/user-guide/configuring#disabling-rules-with-inline-comments

Друг вариант е да модифицираш .eslintrc и да изключиш това правило или да го направиш warning, но ако това е единичен случай, ти препоръчвам да използваш inline коментарите или просто да си го дефинираш.

Иначе линтера няма как да разбере това. Реакт също не го интересува това. t в случая е в контекста на Home компонента, а не на HOC-то и линтера те предупреждава, че имаш нов prop, който не е дефиниран.

Имай предвид, че airbnb правилата са много стриктни. Сигурна ли си, че точно тях искаш да използваш?
 
Мерси за предложенията, за съжаление не е единичен случай, т.к. много части трябват да имат преведени стрингове.

Също така кода трябва да е compatible с линтера на airbnb (стриктни правила == малко проблеми в големи екипи).

Направих си един обект, който екстендвам в проптайпс на компонентите, които използват i18next, за да не трябва да пиша всеки път, че е задължителна функция. : )

Не ползвам hooks, защото проекта е започнат преди създаването им.
 
Предполагам поради consistency reasons нямате право да променяте към functional components?

Ако има вариант за смяна, силно препоръчвам да минете на hooks. И в твоя случай ще трябва да използваш само useTranslation без това да се подава като prop на компонента, което ще намали props check-а, за неща, които не са реално пряко свързани с компонента (като t).

Ако не, магическата пръчка. :D

Може ли пример какво точно си направила, че ми стана интересно.
 
Мхм, проекта е на финална права. Предполагам в бъдеще ще инвестират време и в това, но не съм сигурна.

Какви са предимствата на hooks пред class компонентите?

Аз от скоро се занимавам с React и на теория разбирам нещата, но имам много малко опит и "this vs. that" са ми тъмна Индия.

Това, което направих накратко е:

src/utilities/propTypes.js
Код:
import PropTypes from 'prop-types';

export const hasTranslations = {
  t: PropTypes.func.isRequired,
};

src/Home.jsx:
Код:
Home.propTypes = {
  ...hasTranslations,
  otherProp: PropTypes.string.isRequired,
};

Изглежда ми по-изчистено и self-describing от t: PropTypes.func.isRequired на всяко. едно. място. Ще видим дали ще мине CR. :D
 
Според мен hooks и въобще functional components правят кода по-изчистен, и съответно, разбираем.

Ще добавя и че използването на типизиран език (например typescript) си е задължително ако проекта има повече от 2 компонента.
 
1. Hooks ти помагат да достъпиш API-а на доста по-ниско ниво и ти дава повече свобода и контрол.

2. Забравяш за Stateful/Stateless компоненти. Всеки компонент може да е stateful или stateless по всяко време без да се налага да преминаваш от функционален компонент към класов. Вземи следния случай: в един момент доста stateless компоненти трябва всъщност да контролират даден state, иначе всичко трябва да се подава надолу чрез props и така родителския компонент е затрупан със стейт, който не му е в контекста. Чрез hooks, не е нужно да променяш функционалния компонент към класов. А и както знаеш, класовите компоненти се водят stateful и добавят допълнителен overhead към приложението. Чрез hooks не е така, защото в случая няма да използваш никой от lifecycle методите, а просто ще добавиш стейт към компонента.

3. Премахваш класовете. Изцяло можеш да пишеш фунционално. Това ще окаже ефект и върху размера на бъндъла, защото babel няма да има нужда да прави магии да конвертира класове към функции(което накрая се отразява в повече код отколкото е нужно).

4. State-а се управлява много по-лесно. Забравяш за nested object state, когато имаш голям компонент, който трябва да контролира голям брой стейтове. Също, когато стейта е nested, много по-лесно се контролира без да се налага да използваш nested spreading, докато стигнеш до обекта, който искаш да промениш.

5. useEffect() замества повечето lifecycle методи - componentDidMount(), componentWillUpdate() и т.н. Предимството е, че можеш да имаш колкото искаш useEffect() с различна логика, която да контролира ъпдейтването на компонента.

6. Momoization-а прави нещата доста удобни. Лесно можеш да "кешираш" тежки таскове, когато нещо изисква изчисления (computation), което прави компоненти доста по-леки.

7. Лесно се създават custom hooks, които помагат доста с decoupling на приложението. Много неща могат да се изведат като hooks и използват, когато са нужни. Да речем използваш Axios за заявки към API. Всичко добре, обаче искаш, когато нещо се зарежда (изчакване на отговор от сървъра) да контролираш някой spinner и когато е готово да изведеш резултатите.
В много от случаите добавяш още state към компонента, за да контролираш зареждането. Е, да, но това в един момент трябва да го добавиш на повечето компоненти и да контролираш стейта за всеки един компонент.
В този случай, можеш да си създадеш hook, да речем useAxios(), който вътршно контролира стейта за зареждане и ти просто го връщаш на компонента използващ този hook.

Код:
function Home() {
    let [isLoading, data] = useAxios(url);
}

При зареждане на компонента useAxios(url) ще се задейства, ще направи рикуеста и ще ъпдейтва isLoading и data при всяка настъпила промяна.
Така стейта си стои в useAxios hook-а, а стейта на компонента остава чист и само по предназначение.

Може да има още причини, но не се сещам да допълня.

=======================

Колкото до решението, можеш да направиш и друго.
Просто направи нов компонент, който екстендва Component - да речем TranslationComponent и сложи тази логика там.

Код:
import { Component } from "react";
import PropTypes from "prop-types";
import {withTranslation} from "react-i18next";

class TranslationComponent extends Component
{
    constructor(props) {
        super(props);

        const { t } = this.props;
        this.t = t;
    }
}

TranslationComponent.propTypes = {
    t: PropTypes.func.isRequired
};

export default withTranslation()(TranslationComponent);

Код:
import React from 'react';
import TranslationComponent from "./TranslationComponent";

class Home extends TranslationComponent {
    constructor(props) {
        super(props);
        // some default values are set here
    }

    componentDidMount() {
        // some http requests are happening here
    }

    render() {
        const t = this.t;
        return (
            <h1>{t('pageHome:title')}</h1>
        );
    }
}

export default Home;

Понеже в случая wrap-ваш TranslationComponent не съм сигурен при грешка как ще изглежда stack trace-а, но би трябвало да получиш информация от кой компонент идва проблема.
 
офтопик:
Абе пичове и момичета, на какъв език говорите тука :D 3 пъти прочетох цялата тема и нищо не разбрах. Reac (framework) рамката ли става въпрос? Май ще залягам яко над тетрадките :shock: :shock: :shock: хвърлете някакви уроци ще са от ползва , стига да имате време :dance: :dance: :dance:
 
Ticketa каза:
офтопик:
Абе пичове и момичета, на какъв език говорите тука :D 3 пъти прочетох цялата тема и нищо не разбрах. Reac (framework) рамката ли става въпрос? Май ще залягам яко над тетрадките :shock: :shock: :shock: хвърлете някакви уроци ще са от ползва , стига да имате време :dance: :dance: :dance:

Всъщност, React не е framework (като Vue и Angular), а библиотека.

За материали започни от официалния сайт.
 
Много благодаря за обяснението на разликите между hooks и class comp.

Аз си мислех, че като са с класове и ползваш тия lifecycle методи componentDid еди какво си, componentWill еди какво си по-лесно се чете/разбира какво става. Предполагам, че много зависи как си структурираш кода. Ще ги разгледам по-подробно.

ПС: Вече разбирам как се чувстват даката и терориста :D Попитах нещо за propTypes и преминахме на hooks и що няма тайпскрипт. Добре, че не се включи и някой, който да каже махни js и остави бекенда да превежда нещата.

Ще добавя и че използването на типизиран език (например typescript) си е задължително ако проекта има повече от 2 компонента.

Сериозно?
 
Хаха, hooks просто беше един от вариантите за решаване на проблема ти. Трябваше да ги намеся. :D
 
Fakeheal каза:
Ще добавя и че използването на типизиран език (например typescript) си е задължително ако проекта има повече от 2 компонента.

Сериозно?

Абсолютно сериозно. Типовете правят живота на програмиста по-поносим. Не го казвам точно на теб, а на всички заинтересовани.
 

Горе