A state container for React applications.
npm install @virtuous/react-storeReact Store is a very simple but reliable state container for
React applications.
It helps you write React applications that store application state by replicating
the way how Redux works with almost
the same mechanisms - but completelly without Redux - all done in pure React
using React's Context API.
It provides you with React Hooks and React HOCs for you to be able to easily
access the store functions and data you need.
To install the stable version with npm:
``sh`
npm install --save @virtuous/react-store
To install the stable version with yarn:
`sh`
yarn add @virtuous/react-store
The React Store follows the concepts of Redux. This means that the whole state of
your app is stored in an object tree inside a React Context.
The only way to change the state tree is to emit an action and then having a
reducer applying the changes to the store portion.
To get the store set up, you only need to wrap the store component around your
application components and pass in your reducer:
`js
import React from 'react';
import { Store, combineReducers } from '@virtuous/react-store';
// A simple reducer.
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
const rootReducer = combineReducers({ counter });
function App() {
{/ Your application goes here /}
}
`
A reducer manipulates its own state in response to actions dispatched to the store. This follows
the same principles that are described in the original Redux Documentation.
In the above example we see a very simple reducer, that increments or decrements the counter state.
React Store provides a combineReducers helper that lets you combine multiple reducers
together to a more complex state. It works in the exact same way as it is described
in the Redux Documentation.
There are multiple ways how you can dispatch an action with the React Store.
The easiest is the dispatch() helper, that lets you dispatch an action from
anywhere in your code:
`js
import { dispatch } from '@virtuous/react-store';
dispatch(increment({ type: 'INCREMENT' }));
`
You can use this helper anywhere. Even in React components. It does not to anything
else but the store.
If your code is based in React Hooks and you want to continue using this
paradigm, you can use the useDispatch() React Hook:
`jsx
import { useDispatch } from '@virtuous/react-store';
function MyComponent() {
const dispatch = useDispatch();
function increment() {
dispatch({ type: 'INCREMENT' });
}
return (
)
}
`
There are cases where it does not make sense to write a functional component. Or it is simply
not possible. For these rare cases, React Store provides the withDispatch() higher order component:
`jsx
import React from 'react';
import { withDispatch } from '@virtuous/react-store';
class MyComponent extends React.Component {
increment = () => {
this.props.dispatch({ type: 'INCREMENT' });
}
render() {
return (
)
}
}
export default withDispatch(MyComponent);
`
You might ask yourself "can I still use selectors with this tool?". The answer is YES.
Reselect is inspired and meant
to be used with Redux, but it is not directly connected to it. Therefore
the state and props arguments must not come from Redux. You could in
fact store the state completely by your own and still use reselect.
Let's discover the way, how you can access store data in React Store.
Again, the easiest way to do that, is to use the select() helper, that lets you access
data from anywhere in you codebase:
`js
import { createSelector } from 'reselect';
import { select } from '@virtuous/react-store';
const getCounter = createSelector(
state => state.counter
);
const count = select(getCounter);
`
You can als use the React Hook to access data inside your functional component:
`jsx
import React from 'react';
import { useSelector } from '@virtuous/react-store';
import { createSelector } from 'reselect';
const getCounter = createSelector(
state => state.counter
);
function MyComponent() {
const count = useSelector(getCounter);
return (
// The component output.
)
}
`
We understand that is hard to refactor your codebase all at once. Maybe you made the decission
to switch from Redux to React Store, but you can't invest the time to get rid of everthing
related to Redux. Therefore React Store also provides you with its own implementation
of React Redux's connect() Higher Order Component (HOC). We understand that it is very likely
that you use this module to connect your Redux store with your React application.
`jsx
import { createSelector } from 'reselect';
import { connect } from '@virtuous/react-store';
function MyComponent({ increment, decrement, counter }) {
/ Your component logic /
}
const getCounter = createSelector(
state => state.counter
);
function mapStateToProps(state) {
return {
counter: getCounter(state),
};
}
function mapDispatchToProps(dispatch) {
return {
increment: () => dispatch({ type: 'INCREMENT' }),
decrement: () => dispatch({ type: 'DECREMENT' }),
};
}
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent);
`
> REMEMBER: We can not provide every functionality that the original react-redux moduleconnect()
> provides. Therefore the only two arguments the HOC accepts,mapStateToProps
> are and mapDispatchToProps`. It is only meant to help you migrate.