Using Cookies with React, Redux and React Router 4

Bonus: Passing Cookies and Redux Actions to Formik handlers

Cookies, a mechanism for persisting data locally in a browser, can be incorporated into your React project in a matter of minutes. If you have React Router 4 and React Redux installed, some extra prop management is required to get your cookie object arriving at the correct Components.

Let’s go through installing the react-cookie package from npm, before configuring our CookiesProvider, and start using cookies in a project. I will also document how to pass your cookies and Redux actions though a Formik handler (my preferred form management package).

Installation

React Cookie is the standard package for cookie integration, summoning over 40k daily downloads at the time of this writing.

Find it at: https://www.npmjs.com/package/react-cookie

Install it into your React project with npm i react-cookie and we are good to go.

Configuration

react-cookie provides a <CookieProvider> component that you wrap around your root <App> component. This sets a cookies object, and allows us to start using cookies anywhere within this component.

If we also have React Router and Redux installed, your index.js file may look something like this after integrating cookies:

index.js

...
import { CookiesProvider } from 'react-cookie';
let initialStore = {
...
};
const store = createStore(rootReducer, initialStore);ReactDOM.render( <CookiesProvider>
<BrowserRouter>
<Provider store={store}>
<App />
</Provider>
</BrowserRouter>
</CookiesProvider>,
document.getElementById('root'));

Here, the CookiesProvider is wrapping our BrowserRouter and Redux Provider component. Import the component with import { CookiesProvider } from ‘react-cookie’; .

App.js

Now, within App.js (or your root app component), the following configuration is required:

  • Use withCookies() to give the app access to cookies. We call this function when exporting the component.
  • If using React Router, pass the cookies prop into your Route components that require them.

This is what the configuration looks like:

...
import { withCookies } from 'react-cookie';
class App extends Component {render() {
return (
<div>
<Switch>
<Route
path="/"
render={() => (<HomeContainer cookies={this.props.cookies}/>)}
/>
</Switch>
</div>
);
}
}
export default withCookies(App);

There are a couple of notes to take with this snippet of code:

  • Use withCookies() with your export default statement. Similar to the way Redux wraps containers around components to inject state into props, withCookies will inject the cookies object as a prop into App.
    We can then access this.props.cookies within App.
  • React Router: if you are using the component prop within your Route components, this needs to be changed to the render prop. The render prop allows us to specify an inline function and pass props to the component we are rendering. If you are currently using component, change:
component={HomeContainer}

to:

render={() => (<HomeContainer cookies={this.props.cookies}/>)}

HomeContainer (Redux container)

React Router has now passed cookies into a redux container component. Now it is the containers’ responsibility to give it’s presentational component the cookies object, if needed.

To strictly adhere to the container vs presentational ideology, you may wish to carry out cookie functionality in the container component only. But in reality there will be use cases where you may wish to set and get cookies within your presentational components — therefore it is useful to know how.

Within Redux’s mapStateToProps and mapDispatchToProps functions, use the ownProps argument to access props passed into the component.

ownProps gives us access to everything injected into the component, including React Router configuration and our cookies object:

const mapStateToProps = (state, ownProps) => {
return({
state: state,
cookies: ownProps.cookies,
});
};

Let’s take a look at the entire Redux setup here, providing a container for my Home component (sorry Redux, I like to define the container component under the presentational to save juggling between files and folders):

class Home extends React.Component {
...
}
const mapStateToProps = (state, ownProps) => {
return({
state: state,
cookies: ownProps.cookies,
});
};
export const HomeContainer = connect(
mapStateToProps,
null
)(Home);
export default HomeContainer;

mapDispatchToProps has been left as null, as we are not demonstrating dispatching of actions. Similarly, if you wish to not pass any props into your presentational, use null for mapStateToProps, followed by mapDispatchToProps.

Get and Set Cookies

Great, now our cookies are accessible within the Home component. You are free to set and get cookies within the component by accessing the prop directly:

//get this.props.cookies
const { cookies } = this.props;
//setting a cookie
cookies.set('name', 'Ross', { path: '/' });
//getting a cookie
cookies.get('name');

Here we use / as our path, so the name cookie is accessible from every page in our app. We are not limited to path as the only configurable option: we can also set expiry, maxAge, domain, secure (accessible through HTTPS only?), and httpOnly (accessible only through your http server?).

As well as get, we can also call getAll to fetch all the cookies, or remove to remove a cookie.

If you are removing a cookie with remove(), make sure to include the same path you used when setting it.

Check out the cookies options on npmjs for all options available.

Passing the cookie prop into Formik handlers

Formik Github: https://github.com/jaredpalmer/formik

What may not seem obvious upon browsing the Formik documentation is how to pass your component props into a Formik handler, like onSubmit. It may make sense to handle some cookie updates within this block of code.

The solution is quite simple, by setting a default value for Formik’s provided props argument passed into the handler:

const handleSubmit = (values, { props = this.props, setSubmitting }) => {   //handle form submission
...
//set cookie
props.cookies.set('name', values.name, { path: '/' });

setSubmitting(false);

//update state, do something else...
props.handleStateFromRedux(Object.assign({}, values));
}

<Formik
onSubmit={handleSubmit}
...
/>

Check out the last line — I have also called a Redux action in here, as all my props are available via the props argument. In this case we could use mapDispatchToProps within our HomeContainer.

This wraps up setting and getting cookies in React!

Programmer and Author. Director @ JKRBInvestments.com. Creator of LearnChineseGrammar.com for iOS.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store