Как преобразовать функциональный компонент с помощью хуков в компонент класса - PullRequest
0 голосов
/ 21 февраля 2020

Я пытаюсь бросить вызов себе, чтобы преобразовать свой курсовой проект, который использует ловушки, в тот же проект, но без необходимости использовать ловушки, чтобы узнать больше о том, как делать вещи с компонентами класса. В настоящее время мне нужна помощь, чтобы выяснить, как реплицировать ловушку useCallback внутри обычного компонента класса. Вот как это используется в приложении.

export const useMovieFetch = movieId => {
    const [state, setState] = useState({});
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(false);

    const fetchData = useCallback(async () => {
        setError(false);
        setLoading(true);

        try{
            const endpoint = `${API_URL}movie/${movieId}?api_key=${API_KEY}`;
            const result = await(await fetch(endpoint)).json();
            const creditsEndpoint = `${API_URL}movie/${movieId}/credits?api_key=${API_KEY}`;
            const creditsResult = await (await fetch(creditsEndpoint)).json();
            const directors = creditsResult.crew.filter(member => member.job === 'Director');

            setState({
                ...result,
                actors: creditsResult.cast,
                directors
            });

        }catch(error){
            setError(true);
            console.log(error);
        }
        setLoading(false);
    }, [movieId])

useEffect(() => {
        if(localStorage[movieId]){
            // console.log("grabbing from localStorage");
            setState(JSON.parse(localStorage[movieId]));
            setLoading(false);
        }else{
            // console.log("Grabbing from API");
            fetchData();
        }
    }, [fetchData, movieId])

    useEffect(() => {
        localStorage.setItem(movieId, JSON.stringify(state));
    }, [movieId, state])

    return [state, loading, error]
}

Я понимаю, как реплицировать другие хуки, такие как useState и useEffect, но я изо всех сил пытаюсь найти ответ для альтернативы useCallback. Спасибо за любые усилия, вложенные в этот вопрос.

Ответы [ 2 ]

1 голос
/ 21 февраля 2020

TL; DR

В указанном вами примере c useCallback используется для генерации ссылочного свойства для передачи другому компоненту в качестве реквизита. Вы делаете это, просто создав bound метод (вам не нужно беспокоиться о dependencies, как вы это делаете с хуками, потому что все «зависимости» поддерживаются в вашем экземпляре как props или state.

class Movie extends Component {

    constructor() {
        this.state = {
            loading:true,
            error:false,
        }
    }

    fetchMovie() {
        this.setState({error:false,loading:true});

        try {
            // await fetch
            this.setState({
                ...
            })
        } catch(error) {
            this.setState({error});
        }
    }

    fetchMovieProp = this.fetchMovie.bind(this); <- this line is essentially "useCallback" for a class component

    render() {
        return <SomeOtherComponent fetchMovie={this.fetchMovieProp}/>
    }

}

Немного больше о зацепках функциональных и классовых компонентов

Прекрасная вещь в useCallback состоит в том, чтобы реализовать его на компоненте класса, просто объявив свойство экземпляра, которое функция (привязанная к экземпляру) и все готово.

Цель useCallback - ссылочная целостность, поэтому, в основном, ваши React.memo и React.PureComponent будут работать правильно.

const MyComponent = () => {
  const myCallback = () => { ... do something };
  return <SomeOtherComponent myCallback={myCallback}/> // every time `MyComponent` renders it will pass a new prop called `myCallback` to `SomeOtherComponent`
}
const MyComponent = () => {
  const myCallback = useCallback(() => { ... do something },[...dependencies]);
  return <SomeOtherComponent myCallback={myCallback}/> // every time `MyComponent` renders it will pass THE SAME callback to `SomeOtherComponent` UNLESS one of the dependencies changed
}

Чтобы «копировать» useCallback в компонентах класса, вам не нужно ничего делать:

class MyComponent extends Component {

   method() { ... do something }

   myCallback = this.method.bind(this); <- this is essentially `useCallback`

   render() {
     return <SomeOtherComponent myCallback={this.myCallback}/> // same referential integrity as `useCallback`
   }

}

Вы обнаружите, что многие из hooks в действительности это просто механизмы для создания переменных, которые являются «экземплярами» (подсказка: «экземпляр» - это Fiber )

0 голосов
/ 21 февраля 2020

Вы можете повторить поведение useCallback, используя запомненную функцию для данного входа (например: movieId)

Вы можете использовать loda sh метод

для более глубокого понимания, проверьте здесь

...