react-redux-partial
v0.2.0
Published
Library to improve performance when you have many components connected to different part of the store. Also it helps to create connected components which are independent of shape of root redux store.
Downloads
89
Maintainers
Readme
react-redux-partial
This library is a wrapper of the original react-redux
library and use it inside. react-redux-partial
has beed created for 2 reasons:
- improve performance of an application when large amount of connected components are used
- write connected react-components which are independent of a shape of redux store
Performance improvement
Consider, you have a redux store of this interface:
interface PageState {
loginForm: LoginFormType;
items: SomeItemsType;
}
And you have a few dozens of components connected to the items
field of the store. Then each action which changes loginForm
will cause call of all selectors of components connected to theitems
. It can be slowly.
Using react-redux-partial
you can easy connect components to the items
field such way the corresponding selectors are called when only the items
fields is changed.
Independent connected components
Using react-redux-partial
you can create a connected to a store component which can work with a state of some interface. For example:
interface LoginFormType {
login: string;
password: string;
}
And then you can reuse this component on any page where a redux state has the login form data in any field.
API
createConnects
createConnects
function returns a set of methods to connect component to a part of a redux store.
import { createConnects } from 'react-redux-partial';
type LoginFormType = {
login: string;
password: string;
};
const { connect } = createConnects<LofinFormType>();
createConnects
returns an object with fields:
- context
- useDispatch
- useSelector
- useStore
- connect
- Provider
- withProvider
context
createConnects
returns a new context
object. It can be use directly or as a parameter of original Provider
and connect
from react-redux
. All other methods returned by createConnects
work only with this context.
useDispatch, useSelector, useStore, connect
These functions work as original useDispatch
, useSelector
, useStore
, connect
functions from react-redux
but only with a context
returned by the same createConnects
call.
Provider
The Provider
component adds a store to react context. To get the store from context you can use the context
returned by createConnects
or any of methods useDispatch
, useSelector
, useStore
, connect
.
Pass a store
You can use Provider
as you usually use the react-redux
provider.
import { render } from 'react';
import { createConnects } from 'react-redux-partial';
import { createStore } from 'redux';
import SomeComponent from './SomeComponent';
type LoginFormType = {
login: string;
password: string;
};
const store = createStore(/* arguments */);
const { Provider, connect } = createConnects<LofinFormType>();
const ConnectedComponent = connect(/* arguments */)(SomeComponent);
render(
<Provider store={store}>
<ConnectedComponent />
</Provider>,
element
);
Pass a parent context
Also you can create some ConnectedComponent
and use it with stores which contain a state of different types.
Component.tsx
export type LoginFormType = {
login: string;
password: string;
};
const { Provider, connect } = createConnects<LofinFormType>();
export const ConnectedComponent = connect(/* arguments */)(SomeComponent);
export { Provider };
You can pass to the Provider a parent context and a field where is a state of type LoginFormType
.
import { render } from 'react';
import { createConnects } from 'react-redux-partial';
import { createStore } from 'redux';
import ConnectedComponent, {
LoginFormType,
Provider as ConnectedComponentProvider,
} from './Component';
type PageStateLoginFormType = {
loginForm: LoginFormType;
};
const store = createStore(/* arguments */);
const { Provider, context } = createConnects<PageStateLoginFormType>();
render(
<Provider store={store}>
<ConnectedComponentProvider context={context} fields="loginForm">
<ConnectedComponent />
</ConnectedComponentProvider>
</Provider>,
element
);
Selectors which are passed to connect
will be invoked only if the loginForm
field is changed. This can improve a page performance.
Also you can pass a select
props if you want to transform parent state to chils state. For example:
import ConnectedComponent, {
LoginFormType,
Provider as ConnectedComponentProvider,
} from './Component';
type PageStateLoginFormType = {
loginForm: {
email: string;
pass: string;
};
/** some other fields */
};
function selector(state: { email: string; pass: string }): LoginFormType {
return {
login: state.email,
password: state.pass,
};
}
render(
<Provider store={store}>
<ConnectedComponentProvider
context={context}
fields="loginForm"
select={selector}
>
<ConnectedComponent />
</ConnectedComponentProvider>
</Provider>,
element
);
Or you can pass an object instead of a string to fields
prop.
import ConnectedComponent, {
LoginFormType,
Provider as ConnectedComponentProvider,
} from './Component';
type PageStateLoginFormType = {
user: {
email: string;
phone: string;
};
pass: string;
orders: any[];
};
function selector(state: {
user: {
email: string;
};
pass: string;
}): LoginFormType {
return {
login: state.user.email,
password: state.pass,
};
}
render(
<Provider store={store}>
<ConnectedComponentProvider
context={context}
fields={{
user: { email: true },
pass: true,
}}
select={selector}
>
<ConnectedComponent />
</ConnectedComponentProvider>
</Provider>,
element
);
For each prop you want to pass to a child provider you should specify true
. Also you can use select
prop to transform parent state.
Use custom partial provider instead of original
I some cases you may have to use a original react-redux
provider in a page root. If you have some components which are connected with methods returned by createConnects
, then you should use a Provider
component from react-redux-partial
instead of original. It has the same behavior but turns on performance optimization.
Override original react-redux context
If you want to use some component connected by original connect
you can you use OverrideStoreProvider
to connect it to a partial store. It can improve performance.
With partial root provider.
import { createConnects, OverrideStoreProvider } from 'react-redux-partial';
const { Provider, context } = createConnects();
const store = createStore();
<Provider store={store}>
...
<OverrideStoreProvider context={context} fields="someField">
<ConnectedComponent />
</OverrideStoreProvider>
...
</Provider>;
With original root provider.
import { Provider } from 'react-redux';
import { OverrideStoreProvider } from 'react-redux-partial';
const store = createStore();
<Provider store={store}>
...
<OverrideStoreProvider fields="someField">
<ConnectedComponent />
</OverrideStoreProvider>
...
</Provider>;