All streams
Search
Write a publication
Pull to refresh
4
0
Send message
Не сразу понял полет мысли. Есть такое ;)
Немного неэквивалентно: хук useValue вызывает onValueChange лишь после рендера, хотя на самом деле может быть так и лучше. Сложнее. Но чертовски элегантно. Аплодирую стоя. Спасибо.
Ваш пример можно упростить.
Вынесите хуки тоже в класс, тогда не придется передавать зависимости от хуков этого компонента и не нужно будет возвращать функции-эффекты.

Если я всё правильно понял, вы предлагаете писать так:
Код
interface IMembers<T> {
    onRender(props: T): JSX.Element;
}

function useMembers<P, T extends IMembers<P>>(ctor: (new () => T), props: P) {
    const ref = useRef<T>();
    if (!ref.current) {
        ref.current = new ctor();
    }
    ref.current.onRender(props);
}

export function SomeComponent(props: IProps) {
    return useMembers(Members, props);
}

class Members extends IMembers<IProps> {
    ...
    private deps: IDeps;

    onRender = (props: IProps) => {
        const [numValue, setNumValue] = React.useState(0);
        const [strValue, setStrValue] = React.useState("");
        
        this.deps = { props, numValue, setNumValue, setStrValue };
        
        React.useEffect(this.intervalEffect, []);

        return <div>
            <span>{`Число = ${numValue}`}</span>
            <Input type="text" onChange={this.onTextChanged} value={strValue} />
            <Button onClick={this.onBtnClick}>-10</Button>
        </div>;
    }
    ...
}

Функция компонента опустела, код полностью переехал в класс. Что мы выиграли? Отказались от одной операции деструктуризации объекта
const { onTextChanged, onBtnClick, intervalEffect } = useMembers(...
, добавив префиксы this к названиям функций. Перенесли объявление
private deps: IDeps;
в реализацию класса.
На мой взгляд — сомнительное упрощение. Читаемость кода ухудшилась. Я предпочту остаться в парадигме функционального компонента: хуки в основной функции, перенося в класс только громоздкие функции с зависимостями.
А за комментарий спасибо.
Сразу извинюсь за стиль изложения — писатель я неопытный. Пример полностью синтетический и бессмысленный. Обёртками useCallback я намеренно замусорил код (а чтоб обосновать их применение перешел от простых элементов input и button к вымышленным компонентам Input и Button), чтоб показать эффективность собственного приёма (useMembers), при использовании которого useCallback не понадобятся.
Прием с использованием useMembers пришел мне в голову на гораздо более сложном примере, когда функциональный компонент раздулся до неприличных размеров, массивы зависимостей у функций вырастали элементов до 7. Я уже отчаялся отладить этот компонент, переписал его в виде класса, отладил, а позже придумал вынести обработчики событий из функционального компонента в методы класса.
К моему удивлению, такого метода нигде в интернете не нашел, поэтому решил поделиться здесь.

Information

Rating
Does not participate
Registered
Activity