rickbeerendonk / redux-react-hook

React Hook for accessing state and dispatch from a Redux store

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

redux-react-hook

React hook for accessing mapped state from a Redux store.

Build Status NPM Bundle Size

Table of Contents

Install

# Yarn
yarn add redux-react-hook

# NPM
npm install --save redux-react-hook

Usage

NOTE: React hooks currently require react and react-dom version 16.7.0-alpha.0 or higher.

In order to use the hooks, your Redux store must be in available in the React context from StoreProvider.

Store in Context

Before you can use the hook, you must provide your Redux store via StoreProvider:

import {createStore} from 'redux';
import {StoreProvider} from 'redux-react-hook';
import reducer from './reducer';

const store = createStore(reducer);

ReactDOM.render(
  <StoreProvider value={store}>
    <App />
  </StoreProvider>,
  document.getElementById('root'),
);

useMappedState(mapState)

Runs the given mapState function against your store state, just like mapStateToProps.

const state = useMappedState(mapState);

If your mapState function doesn't use props or other component state, declare it outside of your stateless functional component:

import {useMappedState} from 'redux-react-hook';

// Note how mapState is declared outside of the function -- this is critical, as
// useMappedState will infinitely recurse if you pass in a new mapState
// function every time.
const mapState = state => ({
  lastUpdated: state.lastUpdated,
  todoCount: state.todos.length,
});

export default function TodoSummary() {
  const {lastUpdated, todoCount} = useMappedState(mapState);
  return (
    <div>
      <div>Count: {todoCount}</div>
      <div>Last updated: {new Date(lastUpdated).toString()}</div>
    </div>
  );
}

If you need to use props or other component state in your mapState function, memoize the function with useCallback:

import {useMappedState} from 'redux-react-hook';

function TodoItem({index}) {
  // Note that we pass the index as a dependency parameter -- this causes
  // useCallback to return the same function every time unless index changes.
  const mapState = useCallback(state => state.todos[index], [index]);
  const todo = useMappedState(mapState);

  return <li>{todo}</li>;
}

useDispatch()

Simply returns the dispatch method.

import {useMappedState} from 'redux-react-hook';

function DeleteButton({index}) {
  const dispatch = useDispatch();
  const deleteTodo = useCallback(() => dispatch({type: 'delete todo', index}), [
    index,
  ]);

  return <button onClick={deleteTodo}>x</button>;
}

Example

You can try out redux-react-hook right in your browser with the Codesandbox example.

To run the example project locally:

# In one terminal, run `yarn start` in the root to rebuild the library itself
cd ./redux-react-example
yarn start

# In another terminal, run `yarn start` in the `example` folder
cd example
yarn start

FAQ

How do I fix the error "Too many re-renders. React limits the number of renders to prevent an infinite loop."

You're not memoizing the mapState function. Either declare it outside of your stateless functional component or wrap it in useCallback to avoid creating a new function every render.

More info

Hooks are really new, and we are just beginning to see what people do with them. There is an open issue on react-redux discussing the potential. Here are some other projects that are adding hooks for Redux:

Thanks

Special thanks to @sawyerhood and @sophiebits for writing most of the hook! This repo was setup with the help of the excellent create-react-library.

Contributing

Contributions are definitely welcome! Check out the issues for ideas on where you can contribute. See the CONTRIBUTING.md file for more details.

License

MIT © Facebook Inc.

About

React Hook for accessing state and dispatch from a Redux store

License:MIT License


Languages

Language:TypeScript 86.5%Language:JavaScript 10.9%Language:HTML 2.6%