Use react hooks with react-redux in typescript
Tags: react, javascript, typescript, redux
Published: 2020-09-20 00:03:33

<p>
	It's been more than a year when
	<a title="React" href="https://reactjs.org/" target="_blank" rel="noopener nofollow"
		><strong>React</strong></a
	>
	introduced
	<strong
		><a
			href="https://reactjs.org/docs/hooks-intro.html"
			target="_blank"
			rel="noopener nofollow"
			>hooks</a
		></strong
	>. Many popular libraries that used with ReactJS like
	<a
		title="React Router"
		href="https://reacttraining.com/react-router/web/"
		target="_blank"
		rel="noopener nofollow"
		>React-Router</a
	>,
	<strong
		><a
			title="React Redux"
			href="https://react-redux.js.org/"
			target="_blank"
			rel="noopener"
			>React-Redux</a
		></strong
	>,
	<a
		title="Material UI"
		href="https://material-ui.com/"
		target="_blank"
		rel="noopener nofollow"
		>Material UI</a
	>, etc. now support hooks and <strong>functional components</strong>. But
	today in this article, I will show you the new way of accessing store and
	dispatch in your functional component without using
	<a
		title="higher order components"
		href="https://reactjs.org/docs/higher-order-components.html#___gatsby"
		target="_blank"
		rel="noopener nofollow"
		>higher-order components</a
	>, and compare how hooks reduced huge pile of
	<a title="boilerplate" rel="noopener dofollow" href="https://garbagevalue.com/definitions/boilerplate">boilerplate</a>.
</p>
<hr />
<p>
	Related Article:
	<a
		title="Latest Features of Typescript 2020 release"
		href="https://garbagevalue.com/blog/latest-features-of-typescript-3-8-2020-release"
		target="_blank"
		rel="noopener dofollow"
		>Latest Features of Typescript 2020 release</a
	>
</p>
<hr />
<h2 id="1-what-are-hooks-in-react-js">
	<a href="#1-what-are-hooks-in-react-js">1. What are hooks in ReactJS?</a>
</h2>
<p>
	<img
		src="https://ik.imagekit.io/garbagevalue/what-are-react-hooks_ATUe2od3Z.jpg?tr=n-lg"
		alt="What are react hooks?"
		width="100%"
		height="auto"
	/>
</p>
<p style="text-align: right">
	<span
		style="
			color: #111111;
			font-family: -apple-system, system-ui, 'San Francisco', 'Helvetica Neue',
				Helvetica, Ubuntu, Roboto, Noto, 'Segoe UI', Arial, sans-serif;
			font-size: 14px;
			white-space: nowrap;
			background-color: #f5f5f5;
		"
		>Photo by&nbsp;</span
	><a
		style="
			box-sizing: border-box;
			background-color: #f5f5f5;
			color: #767676;
			transition: color 0.1s ease-in-out 0s, opacity 0.1s ease-in-out 0s;
			text-decoration-skip-ink: auto;
			font-family: -apple-system, system-ui, 'San Francisco', 'Helvetica Neue',
				Helvetica, Ubuntu, Roboto, Noto, 'Segoe UI', Arial, sans-serif;
			font-size: 14px;
			white-space: nowrap;
		"
		href="https://unsplash.com/@chuttersnap?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText"
		>chuttersnap</a
	><span
		style="
			color: #111111;
			font-family: -apple-system, system-ui, 'San Francisco', 'Helvetica Neue',
				Helvetica, Ubuntu, Roboto, Noto, 'Segoe UI', Arial, sans-serif;
			font-size: 14px;
			white-space: nowrap;
			background-color: #f5f5f5;
		"
		>&nbsp;on&nbsp;</span
	><a
		style="
			box-sizing: border-box;
			background-color: #f5f5f5;
			color: #767676;
			transition: color 0.1s ease-in-out 0s, opacity 0.1s ease-in-out 0s;
			text-decoration-skip-ink: auto;
			font-family: -apple-system, system-ui, 'San Francisco', 'Helvetica Neue',
				Helvetica, Ubuntu, Roboto, Noto, 'Segoe UI', Arial, sans-serif;
			font-size: 14px;
			white-space: nowrap;
		"
		href="https://unsplash.com/s/photos/hook?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText"
		>Unsplash</a
	>
</p>
<p>
	If you're aware of what are hooks in react, you can skip to the
	<a href="#react-redux-hooks-class-vs-functional-component-comparison"
		>next section.&nbsp;</a
	>
</p>
<p>
	React hook is a new concept introduced in
	<a
		title="React 16.8"
		href="https://reactjs.org/blog/2019/02/06/react-v16.8.0.html"
		target="_blank"
		rel="noopener"
		>React 16.8</a
	>, that enables programmers the power to separate the logic from the UI. We
	all know that states used only in react component, so what if there's a logic
	bind with that state, and you want to use it in multiple files? You forced to
	return a JSX, which makes it a functional component. Now, that was the
	motivation.
</p>
<p>
	So now, you can write a functional
	<span style="text-decoration: line-through">component</span> hook, you can do
	everything that you do in a functional component except you can return
	anything rather than just a JSX. Hooks name start with
	<strong>use</strong> like&nbsp;<code>useEffect</code>,
	<code>useState</code> etc. It is not a strict rule, but it considered a
	standard to identify hooks.
</p>
<h2 id="2-react-redux-hooks-class-vs-functional-component-comparison">
	<a href="#2-react-redux-hooks-class-vs-functional-component-comparison"
		>2. React redux hooks: Class vs Functional component comparison</a
	>
</h2>
<p>
	(See the complete code on
	<a
		title="Code Sandbox"
		href="https://codesandbox.io/s/hooks-with-react-redux-example-using-with-typescript-to-reduce-the-react-boilerplate-3lu3b)"
		target="_blank"
		rel="noopener"
		>Code Sandbox</a
	>
</p>
<p>
	I'm writing a simple class component and a functional component that render
	the name of a user. First, we dispatch the name of the user, and next, we
	select the name from the store in the component to display it in the
	component.
</p>
<pre class="language-typescript"><code>import * as React from "react";
import { connect } from "react-redux";
import { TReduxStore, TDispatch } from "./types";
import { AxiosPromise } from "axios";
import { getUser } from "./action";

type IStateProps = Pick&lt;TReduxStore, "user"&gt;;

interface IDispatchProps {
  getUser: (id: string) =&gt; AxiosPromise;
}

interface IProps extends IStateProps, IDispatchProps {}

class ShowUser extends React.Component&lt;IProps&gt; {
  componentDidMount() {
    this.props.getUser("1");
  }

  render() {
    const { user } = this.props;
    return !user ? "Loading..." : &lt;div&gt;User Name: {user.name}&lt;/div&gt;;
  }
}

const mapStateToProps = (state: TReduxStore): IStateProps =&gt; ({
  user: state.user
});

const mapDispatchToProps = (dispatch: TDispatch): IDispatchProps =&gt; ({
  getUser: id =&gt; dispatch(getUser(id))
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(ShowUser);
</code></pre>
<p>
	Above is the
	<a
		href="https://react-redux.js.org/api/connect"
		target="_blank"
		rel="noopener"
		>traditional way of connecting your ReactJS component with the redux</a
	>. You have to write that much code just to request and display the user name.
	Now let's see the same thing in the functional component.
</p>
<pre class="language-typescript"><code>import * as React from "react";
import { useSelector, useDispatch } from "react-redux";
import { TReduxStore, TDispatch } from "./types";
import { getUser } from "./action";

type IStateProps = Pick&lt;TReduxStore, "user"&gt;;

const ShowUser: React.FC = props =&gt; {
  const dispatch = useDispatch&lt;TDispatch&gt;();

  const { user } = useSelector&lt;TReduxStore, IStateProps&gt;(state =&gt; ({
    user: state.user
  }));

  React.useEffect(() =&gt; {
    dispatch(getUser("1"));
  }, [dispatch]);

  return !user ? &lt;div&gt;"Loading..."&lt;/div&gt; : &lt;div&gt;User Name: {user.name}&lt;/div&gt;;
};

export default ShowUser;
</code></pre>
<p>
	As you can see, using hooks, reduced the number of lines to almost half. I'm
	considering you're using the class component, so I'm not explaining that
	snippet. So I'm just explaining the FunctionalComponent.tsx below.
</p>
<h2 id="3-how-to-use-use-dispatch-and-use-selector-react-redux-hooks-in-your-functional-component">
<a href="#3-how-to-use-use-dispatch-and-use-selector-react-redux-hooks-in-your-functional-component">3. How to use useDispatch and useSelector react-redux hooks in your functional component?</a>
</h2>
<p>
	Let's see one by one how to use the
	<strong
		><a
			title="use of useDispatch hook"
			href="https://react-redux.js.org/api/hooks#usedispatch"
			target="_blank"
			rel="noopener"
			>useDispatch</a
		></strong
	>
	and the
	<a
		title="use of useSelector hook"
		href="https://react-redux.js.org/api/hooks#useselector-examples"
		target="_blank"
		rel="noopener"
		><strong>useSelector</strong></a
	>
	to dispatch and select the data from the redux store.
</p>
<p>
	<img
		src="https://ik.imagekit.io/garbagevalue/use-dispatch-and-use-selector_ng2RpmM1L.jpg?tr=n-lg"
		alt="How to use useDispatch and useSelector in react redux typescript"
		width="100%"
		height="auto"
	/>
</p>
<p style="text-align: right">
	<span
		style="
			color: #111111;
			font-family: -apple-system, system-ui, 'San Francisco', 'Helvetica Neue',
				Helvetica, Ubuntu, Roboto, Noto, 'Segoe UI', Arial, sans-serif;
			font-size: 14px;
			white-space: nowrap;
			background-color: #f5f5f5;
		"
		>Photo by&nbsp;</span
	><a
		style="
			box-sizing: border-box;
			background-color: #f5f5f5;
			color: #767676;
			transition: color 0.1s ease-in-out 0s, opacity 0.1s ease-in-out 0s;
			text-decoration-skip-ink: auto;
			font-family: -apple-system, system-ui, 'San Francisco', 'Helvetica Neue',
				Helvetica, Ubuntu, Roboto, Noto, 'Segoe UI', Arial, sans-serif;
			font-size: 14px;
			white-space: nowrap;
		"
		href="https://unsplash.com/@chris_j_scott?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText"
		>Chris Scott</a
	><span
		style="
			color: #111111;
			font-family: -apple-system, system-ui, 'San Francisco', 'Helvetica Neue',
				Helvetica, Ubuntu, Roboto, Noto, 'Segoe UI', Arial, sans-serif;
			font-size: 14px;
			white-space: nowrap;
			background-color: #f5f5f5;
		"
		>&nbsp;on&nbsp;</span
	><a
		style="
			box-sizing: border-box;
			background-color: #f5f5f5;
			color: #767676;
			transition: color 0.1s ease-in-out 0s, opacity 0.1s ease-in-out 0s;
			text-decoration-skip-ink: auto;
			font-family: -apple-system, system-ui, 'San Francisco', 'Helvetica Neue',
				Helvetica, Ubuntu, Roboto, Noto, 'Segoe UI', Arial, sans-serif;
			font-size: 14px;
			white-space: nowrap;
		"
		href="https://unsplash.com/s/photos/hook?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText"
		>Unsplash</a
	>
</p>
<ul>
	<li>
		<h3 id="use-dispatch"><a href="#use-dispatch">useDispatch</a></h3>
		<p>
			useDispatch hook used to get the <strong>redux</strong> dispatch function
			in your functional component or hook. It takes a
			<a
				title="generic type"
				href="https://www.typescriptlang.org/docs/handbook/generics.html"
				target="_blank"
				rel="noopener"
				>generic type</a
			>
			of data dispatch, takes in its parameters. Usually, it is
			<code>{type: string, payload?: any}</code> but as I'm redux-thunk here, so
			its type is
			<code>ThunkDispatch&lt;TReduxStore, {}, TAction&gt;;</code> where
			<code>TReduxStore</code> is the type of the store and
			<code>TAction</code> is <code>{type: string, payload?: any}</code>.
		</p>
	</li>
	<li>
		<h3 id="use-selector"><a href="#use-selector">useSelector</a></h3>
		<p>
			As its name suggests, it gives you the functionality of selecting the data
			from your <strong>redux store</strong>. It takes one parameter, which is a
			callback, where it passes the whole <strong>redux</strong> state, and you
			return the data you want to select from it. So the callback function looks
			like below.
		</p>
		<pre class="language-typescript"><code>function (state) {
    return ({
        user: state.user
    })
}</code></pre>
		<p>
			The same thing I have written is in the flat arrow function format in the
			functional component. It takes two types in its
			<a
				title="generic type"
				href="https://www.typescriptlang.org/docs/handbook/generics.html"
				target="_blank"
				rel="noopener"
				>generic type</a
			>. One is the type of your redux store, and the second is the type you
			want to select from the store. IN my codes, it is represented by
			<code>TReduxStore</code> and <code>IStateProps</code> respectively.
		</p>
	</li>
</ul>

<hr />

<p>The post <a href="https://garbagevalue.com/blog/react-redux-hooks-in-typescript#table-of-content" rel="noopener dofollow" >Use react hooks with react-redux in typescript</a> was originally published on <a href="https://garbagevalue.com/" rel="noopener dofollow">garbagevalue.com</a>