如何使用挂钩将功能组件转换为类组件

时间:2020-02-21 18:22:45

标签: javascript reactjs react-hooks usecallback

我试图挑战自己,将使用钩子的课程项目转换为同一项目,而不必使用钩子来了解有关如何使用类组件做事的更多信息。当前,我需要帮助弄清楚如何在普通的类组件中复制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 个答案:

答案 0 :(得分:3)

TL; DR

在您的特定示例中,useCallback用于生成引用维护的属性,以作为道具传递给另一个组件。您只需创建一个bound方法即可做到这一点(不必像使用钩子那样担心dependencies,因为所有“依赖项”都作为props或state保留在您的实例上。 / p>

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.memoReact.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

答案 1 :(得分:0)

您可以通过使用给定输入(例如:useCallback)的存储功能来复制movieId的行为

您可以使用lodash method

for more in-depth understanding check here