Oct
How to use functional components rather than classes using React Hooks in React Native
React Native has introduced a new feature called ‘React Hooks’ in React 16.8 , which allows you to build whole react native application by functional components.
In the ever-evolving universe of React Native development, keeping awake to-date with the most recent prescribed procedures is urgent. One huge change in React Native development is the developing prominence of practical parts over conventional class parts, on account of the presentation of React Hooks.
Know about ‘React Hooks’ to construct productive and viable mobile application development.
Main reasons to use functional components are :
• It was very hard to re-use stateful logic between components.
• Classes were confusing.
• Understanding of complex component was getting difficult.
Main reason of using classes was:
• State Management
• Lifecycle Methods.
State Management:
Previously, we use class component like this:-
import React, { Component } from 'react'; import {TouchableOpacity,Text} from 'react-native'; class Bank extends Component { state = { balance: [] } balanceHandler = () => { this.setState({ balance: ['100'] } } render() { return ( < TouchableOpacity onPress={this.balanceHandler}> Add Balance ) } }
But now we have implemented same thing with functional component in which state management is done with the help of hook.
import React, { useState } from 'react' import {TouchableOpacity,Text} from 'react-native'; const Bank = props => { const [balance, setBalance] = useState([]) const balanceHandler = () => { setBalance(['100']) } return < TouchableOpacity onPress={this.balanceHandler}> Add Balance }
Note:- useState() is a called Hook.
Lifecycle Methods:
In functional components, we don’t have lifecycle methods as we haven’t use classes here. So let’s see how we can implement lifecycle methods behaviour with functional components.
Let’s understand by an example of http request how can we use functional component instead of componentDidMount .
const Bank = props => { const [userData, setUserData] = useState([]) fetch('url') .then(res => res.json()) .then(fetchedUserData => setUserData(fetchedUserData)) return ( {userData .map(data => ( {data .name} ))} ) }
In above example, it is generating an infinite loop because calling setUserData(…) will also cause the component to re-render – which in turn leads to another Http request and so on.. .
In class based components solution is componentDidMount.
To overcome above problem we will use another Hook called useEffect().
useEffect():
useEffect() hook takes a function as an input and not returns anything. The input function useEffect() takes will be executed after every render cycle.
const Bank = props => { const [userData, setUserData] = useState([]) useEffect(() => { fetch('url') .then(res => res.json()) .then(fetchedUserData => setUserData(fetchedUserData)) }) return ( {userData .map(data => ( {data .name} ))} ) }
So, in the above solution there are two main issues still existing:
• The input function inside of useEffect() executed unnecessarily whenever the component re-renders.
• There is an infinite loop because setUserData() causes the function to re-render.
Solution:
The second argument passed in useEffect() allows us to controls when the First argument of ueEffect() will be executed.
useEffect(() => { fetch('url') .then(res => res.json()) .then(fetchedUserData => setUserData(fetchedUserData)) }, [])
Now, we have passed an empty array ([]) as the second argument in useEffect(). Now it works like componentDidMount.
About componentDidUpdate:
If you want to fetch specific userData, identified by userId and you only want to send Http request when userId changed then you can follow below example by passing userId in array as second argument.
useEffect(() => { fetch('url' + userId) .then(res => res.json()) .then(fetchedUserData => setUserData(fetchedUserData)) }, [userId])
About componentWillUnmount:
Generally we use componentWillUnmount for cleanup work like cleaning event listeners, timers, etc.
useEffect(() => { const timer = setTimeout(() => { // do something }, 2000) return () => { // Cleanup work clearTimeout(timer) } })
Note:- If you return a function from useEffect(),that function will be executed right before the running of function passed to useEffect() and same function will also be executed before the component is removed from the DOM.
About constructor, componentWillMount and componentWillUpdate:
Constructor should be only executed once so we use useEffect() here like componentDidMount because it is the better approach for initialization.
const Bank = props => { useEffect(() => { // work Initialization }, []) return ... }
Note:- componentWillMount and componentWillUpdate are deprecated now.
Ref: https://reactjs.org/docs/hooks-intro.html
Conclusion:
All the problems in the lifecycle methods of React has been resolved by React Hook and functional component has made easy to use stateful logic between components in React native.