I'm trying to challenge myself to convert my course project that uses hooks into the same project but without having to use hooks in order to learn more about how to do things with class components. Currently, I need help figuring out how to replicate the useCallback
hook within a normal class component. Here is how it is used in the app.
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]
}
I understand how to replicate other hooks such as useState
and useEffect
but I'm struggling to find the answer for the alternative to useCallback
. Thank you for any effort put into this question.
TL;DR
In your specific example useCallback
is used to generate a referentially-maintained property to pass along to another component as a prop. You do that by just creating a bound
method (you don't have to worry about dependencies
like you do with hooks, because all the dependencies are maintained on your instance as props or 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}/>
}
}
A bit more about hooks on functional vs class components
The beautiful thing about useCallback
is, to implement it on a class component, just declare an instance property that is a function (bound to the instance) and you're done.
The purpose of useCallback
is referential integrity so, basically, your React.memo
's and React.PureComponent
's will work properly.
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
}
To replicate useCallback
in class components you don't have to do anything:
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`
}
}
You'll find that hooks
in react are just a mechanism to create instance variables (hint: the "instance" is a Fiber) when all you have is a function.
You can replicate the behavior ofuseCallback
by using a memorized function for the given input(eg: movieId
)
You can use lodash method
for more in-depth understanding check here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With