In React, there are a great many ways to implement functionality. In my Flatiron School curriculum, we were initially taught how to build each component as a JS ES6 class, initializing state, using a constructor and taking advantage of component lifecycle methods, such as componentDidMount(), and componentDidUnmount()
As you may gather from their names, these lifecycle methods are run when our component renders to the DOM, and when the rendered component is removed from the DOM.
Enter the functional component.
Functional components are similar to class components in that, when called, our component will render the HTML we tell it to return in the DOM. However, without an ES6 class, we cannot construct a new instance using state, and we loose access to the "this" keyword that is so omnipotent within the context of a class.
Functional components, do, however take full advantage of the JS closure and the wonderful lexical scope that comes with them!
How, then, do we imitate the lifecycle methods and gain access the store (if using Redux) within the scope of a functional component?
Enter the React hook.
Hooks, while sounding intimidating, are simply functions that you can call in your functional component. Hooks are, according to the React docs, simply "functions that let you "hook into" React state and lifecycle features from function components"
They do have a few different rules to guide usage.
Since classes can be given an initial state, and have defined lifecycle methods, you don't need to use hooks in class components.
Hooks must only be called at the top level of your functional component. It is inappropriate to use a hook within a conditional, a loop, or a nested function. Adhering to this guideline will ensure that the hooks are called methodically, which makes them reliable and predictable.
You are able to use many of the same hook within a single component.
For example, if you are using Redux, and needed to access different areas of state, you are able to reuse the useSelector() (a custom hook that ships with React-Redux) hook multiple times- assigning its return value into a variable.
const posts = useSelector((state) => state.posts)
// retrieves what is stored in state.posts and makes it available // in posts.
const comments = useSelector((state) => state.comments)
// both posts and comments are accessible in their respective
// variables within the scope of this functional component
The useState() hook allows you declare a setter and getter, as well as initializing state with a given variable for use locally within your functional component. This is incredibly handy if you are trying to implement a feature that will render conditionally.
const [showForm, setShowForm] = useState(false)
In this example, we pass an initial state value of
`false
to the useState hook. Now, our falsey value will persist, and is accessible by calling our showForm variable. "setShowForm(!showForm)" will set the value of showForm, mimicking a change of state, locally, within our component.
function Post(props){
const [showForm, setShowForm] = useState(false)
return(
<button onClick{() => setShowForm(!showForm)}> Show Form </button>
{ showForm ? <Commentform id={props.id} /> : showForm}
)
}
In this example, we are using the useState() hook to set a boolean. Our Post function will render a button with an onClick event handler that will call our setShowForm function, which is generated by useState() to set the new value of the showForm variable. Here, we are toggling booleans. Finally, in the JSX below our button we are checking the value of the showForm variable with the ternary operator. If showForm returns true, it will render our comment button passing in the props that were passed when our Post() function was called. Else, it will return a falsey value and no comment form will be rendered.
React grants you the ability to even write your own custom hooks! These powerful tools are not only incredibly useful, but they are endlessly customizable.
With hooks, we are able to make our functional components behave like class components!
Top comments (0)