【问题标题】:How to convert functional component using hooks to class component如何使用钩子将功能组件转换为类组件
【发布时间】:2020-06-06 05:14:05
【问题描述】:

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

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

【问题讨论】:

  • 我认为你最好的选择是 shouldComponentUpdate:developmentarc.gitbooks.io/react-indepth/content/life_cycle/…
  • 我会调查一下,看看我能不能让它工作。如果我得到它的工作,我会告诉你。谢谢
  • 仅供参考,功能组件和钩子 API 比类组件 API 更新且通常更推荐,因为它们更擅长实现关注点分离。使用类组件,您只有一个状态对象,以及每个生命周期方法之一,用于实现特定组件的所有逻辑。如果你只是想学习也没关系,但你的课程使用函数式组件和钩子而不是类组件是有原因的。

标签: javascript reactjs react-hooks usecallback


【解决方案1】:

TL;DR

在您的具体示例中,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.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 在 react 中只是一个创建实例变量的机制(提示:“实例”是一个 Fiber)。

【讨论】:

  • 感谢您提供的信息,我会看看这是否会很快奏效。我仍在尝试完全理解它。你能告诉我我认为讲师在这里使用了 useCallback 钩子是否正确,因为他需要在 fetchData 方法中使用 movieId 道具,但 movieId 并不总是相同的。因为movieId发生了变化,所以如果movieId没有变化,useCallback不会创建新方法,但是一旦发生变化,就需要创建一个新的fetchData方法。对吗?
  • @albert_anthony6 100% 成功了。这就是几乎所有钩子的工作方式,它们只有在依赖数组中的某些内容与上次调用钩子时不同时才会“做事”——最好的记忆化。
  • 好吧太好了,我明白他为什么现在用它了;但是,在您的示例中,该方法作为道具传递给其他一些组件,但是讲师对该方法所做的却有所不同。我将使用其余代码编辑问题,以便您了解他是如何使用该方法的。我不认为他将它作为道具传递到任何地方,我可能是错的,但你能看看你自己并告诉我你认为应该做什么吗?
  • 哈,用你的导师用的方式使用回调是无关紧要的。它纯粹用于创建回调道具的参照完整性。没有必要像你的导师那样使用它,它实际上只会让代码变慢,因为现在它必须每次都检查记忆。
  • 只要把fetchData的全部内容放到效果里面就行了。或者,您可以完全提取 fetchData 并将其以 movieId 和状态设置函数作为参数。
【解决方案2】:

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

您可以使用lodash method

for more in-depth understanding check here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 2020-01-29
    • 2020-11-30
    • 2020-12-21
    • 2019-07-11
    相关资源
    最近更新 更多