A lightweight manager for your Context API's.
It helps you to set a standard for your React apps using Context API.
We recommend you to use this along with our custom CLI.
For Javascript documentation, click here.
If you want to follow a tutorial, we recommend this post
React Context Manager obtained some ideas from Redux, such as the structure for actions and some HOC functions for class-based components, but avoiding a lot of extra verbosity and complexity by using React's own Context API.
- Juan Perozo [email protected] (https://github.com/jperozo)
- Max Rondón [email protected] (https://github.com/mrondon)
- Fernando Galindez [email protected] (https://github.com/fergalindez)
To add @talpor/react-context-manager
to your project run the following command in your project folder:
With npm:
npm install --save @talpor/react-context-manager
With yarn:
yarn add @talpor/react-context-manager
Note: React Context Manager works with React >= 16.8, because it uses hooks internally.
This is the data structure of your context. It should be divided by app or by scope, according to your application needs.
The objects inside your scope can be whatever you want and you can access them directly, so we removed the need of using selectors, unlike Redux, though you can still use them if you wish to.
Here is an example:
export interface IStore {
team: {
token: string;
colaborators: any[];
},
test: {
test1: string;
}
}
export const store = {
team: {
token: 'ReactContextManagerRocks',
colaborators: [
{ email: '[email protected]' },
{ email: '[email protected]' },
{ email: '[email protected]' },
...
{ email: '[youremail]@[yourdomain].com' },
},
},
test: {
test1: 'TEST',
}
};
This is how you change the context throughout the component tree. The actions have to be placed inside a scope under the same name as the store portion it changes.
Also, the dispatcher injects the current state portion to the action in case data is needed there.
Finally, actions should return the next state of the application, as shown in this next example:
export interface IUserActions extends Scope<IStore> {
team: {
addColaborator: (state: IStore) => (email: string) => IStore
};
test: {
actionTest: (state: IStore) => (text: string) => IStore
};
}
const actions = {
team: {
addColaborator: state => email => {
const colaborators = [
...state.colaborators,
{ email: '[youremail]@[yourdomain].com' }
];
return { ...state, colaborators };
}
},
test: {
actionTest: state => text => {
return {
...state,
test: {
...state.test,
text
}
};
}
}
};
In order to create a context you need to import a ContextProvider
around the component tree where you want to use it. Here we set it on the root, but it can be done anywhere on the component tree:
index.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import { ContextProvider, initContext } from '@talpor/react-context-manager';
const context = initContext();
const actions = {
test: {
actionTest: state => text => {
return {
...state,
test: {
...state.test,
test1: text
}
};
}
}
};
const store = {
test: {
test1: 'TEST'
}
};
ReactDOM.render(
<ContextProvider actions={actions} store={store} context={context}>
<App />
</ContextProvider>,
document.getElementById('root')
);
Name | Default | Required | Description |
---|---|---|---|
store | N/A | True | This is the initial store of your context. For more info, re-visit the previous section. |
actions | N/A | True | Actions that are to be made avaible on the context. |
context | N/A | True | Context used through the provider's children. |
App.jsx
import React, { useContext, useEffect } from 'react';
import { context } from '../index.jsx';
function App() {
const context = useContext(context);
useEffect(() => {
context.actions.test.actionTest('Hello World!');
}, []);
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
{context.test.test1}
<br />
</p>
<button
className="App-link"
onClick={() => {
context.actions.test.actionTest('Bye World!');
}}
>
Say Goodbye!
</button>
</header>
</div>
);
}
export default App;
And that's it!
That's the way we get our context along the application and the only thing you need to worry about is creating powerful actions.
We understand not all projects would want to use function-based components and, thinking of that, we implemented a HOC (High Order Component) called mapContextToProps
(very similar to Redux), in order to inject the context as props in your component, as you can see next:
import React from 'react';
import { mapContextToProps } from '@talpor/react-context-manager';
import { context } from '../index.js';
class BaseApp extends React.Component {
componentDidMount() {
this.props.actions.test.actionTest('Hello World!');
}
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
{this.props.store.test.test1}
<br />
</p>
<button
className="App-link"
onClick={() => {
this.props.actions.test.actionTest('Bye World!');
}}
>
Say Goodbye!
</button>
</header>
</div>
);
}
}
export default mapContextToProps(context)(BaseApp)('test');