6

我正在尝试挑战自己,将使用钩子的课程项目转换为同一个项目,但不必使用钩子来了解有关如何使用类组件做事的更多信息。目前,我需要帮助弄清楚如何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]
}

我了解如何复制其他钩子,例如useStateanduseEffect但我正在努力寻找替代方法的答案useCallback。感谢您为这个问题付出的任何努力。

4

2 回答 2

12

TL;博士

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

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 )。

于 2020-02-21T19:09:22.237 回答
1

useCallback您可以通过对给定输入使用记忆函数来复制的行为(例如movieId:)

您可以使用lodash 方法

如需更深入的了解,请点击此处

于 2020-02-21T18:59:00.907 回答