Skip to content

Commit 29a7da7

Browse files
Rename to useSubstate
We **sub**scribe to a **sub**set of your state.
1 parent fe71e06 commit 29a7da7

File tree

5 files changed

+84
-88
lines changed

5 files changed

+84
-88
lines changed

README.md

Lines changed: 55 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
# ⚓️ useStore
1+
# ⚓️ useSubstate
22

3-
Lightweight ([<600B minified + gzipped](https://bundlephobia.com/result?p=use-store@0.0.1)) alternative for [react-redux][] using React Hooks.
3+
Lightweight ([<600B minified + gzipped](https://bundlephobia.com/result?p=use-substate)) React Hook to subscribe to a subset of your state.
44

55

66
```js
77
function Component() {
8-
const [mappedState, dispatch] = useStore(state => {
8+
const [substate, dispatch] = useSubstate(state => {
99
return { count: state.count };
1010
});
1111

1212
return (
1313
<div>
14-
{mappedState.count}
14+
{substate.count}
1515

1616
<button
1717
onClick={() => dispatch({ type: "INCREMENT" })}
@@ -23,45 +23,42 @@ function Component() {
2323
}
2424
```
2525

26-
In opposite to [react-redux][], this library only requires a `mapState` function. It is meant to call the `dispatch` function with the action directly. Advanced concepts like `connectAdvanced` or `mapDispatchToProps` are deliberately not supported.
27-
2826
### Features
2927

3028
- ⏬ Lightweight
3129
- ✅ Concurrent React ready (avoids rendering stale state)
32-
- ⚛️ Works with your existing Redux-like store
33-
- 🎮 You’re in full control of your store and can use it outside React as well
3430
- 🐋 Only updates components that need to be updated
35-
- 🔂 Uses an external event subscription to short-circuit context propagation (We’ll see if that works out)
31+
- 🔂 Uses an external event subscription to short-circuit context propagation
3632
- 🎈 Full Flow and TypeScript support coming soon
33+
- ⚛️ Works with your existing Redux-like store
34+
- 🎮 You’re in full control of your store and can use it outside React as well
3735

3836
## Requirements
3937

40-
__⚠️ To use `useStore`, you will need the unstable and experimental React 16.7.0-alpha.__
38+
__⚠️ To use `useSubstate`, you will need the unstable and experimental React 16.7.0-alpha.__
4139

42-
`useStore` can also be used together with [react-redux][] in your existing [Redux][] application.
40+
`useSubstate` can also be used together with [react-redux][] in your existing [Redux][] application. Check out [Comparison To Redux][#comparison-to-redux] for more infomration.
4341

4442
## Installation
4543

4644
```bash
47-
npm install --save use-store
45+
npm install --save use-substate
4846
```
4947

5048
## Usage
5149

52-
You can use `useStore` with your existing [Redux][] store or with a simple alternative (as outlined in [createStore.js](./example/createStore.js)). This package will export
53-
a [React Context](https://reactjs.org/docs/context.html) consumer (`StoreContext`) as well the `useStore` hook.
50+
You can use `useSubstate` with your existing [Redux][] store or with a simple alternative (like [`create-state`](https://github.com/philipp-spiess/create-state)). This package will export a [React Context](https://reactjs.org/docs/context.html) consumer (`SubstateContext`) as well the `useSubstate` hook.
5451

55-
This custom hook will expose an API similar to [`useReducer`](https://reactjs.org/docs/hooks-reference.html#usereducer). The only argument for `useStore` is a `mapState` function which is used to select parts of your store to be used within the component that uses the hook. This allows `useStore` to bail out if unnecessary parts change. Every component that uses this custom hook will automatically subscribe to the store.
52+
This custom hook will expose an API similar to [`useReducer`](https://reactjs.org/docs/hooks-reference.html#usereducer). The only argument for `useSubstate` is a `selectSubstate` function which is used to select parts of your state to be used within the component that uses the hook. This allows `useSubstate` to bail out if unnecessary parts change. Every component that uses this custom hook will automatically subscribe to the store.
5653

57-
The example below will show all steps necessary to use `useStore`:
54+
The example below will show all steps necessary to use `useSubstate`:
5855

5956
```js
6057
import React, { useState } from "react";
6158
import ReactDOM from "react-dom";
6259

63-
import { createStore } from "./createStore";
64-
import { StoreProvider, useStore } from "../";
60+
import createStore from "create-state";
61+
import { SubstateProvider, useSubstate } from "../";
6562

6663
const initialState = { count: 0 };
6764
function reducer(state, action) {
@@ -75,13 +72,13 @@ function reducer(state, action) {
7572
const store = createStore(reducer, initialState);
7673

7774
function App() {
78-
const [mappedState, dispatch] = useStore(state => {
75+
const [substate, dispatch] = useSubstate(state => {
7976
return { count: state.count };
8077
});
8178

8279
return (
8380
<div>
84-
{mappedState.count}
81+
{substate.count}
8582

8683
<button onClick={() => dispatch({ type: "INCREMENT" })}>Increment</button>
8784
<button onClick={() => dispatch({ type: "DECREMENT" })}>Decrement</button>
@@ -90,45 +87,73 @@ function App() {
9087
}
9188

9289
ReactDOM.render(
93-
<StoreProvider value={store}>
90+
<SubstateProvider value={store}>
9491
<App />
95-
</StoreProvider>,
92+
</SubstateProvider>,
9693
rootElement
9794
);
9895
```
9996

100-
[![Edit useStore Example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/4w406kwy44)
97+
[![Edit useSubstate Example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/4w406kwy44)
98+
99+
## Comparison To [Redux][]
100+
101+
[Redux][] itself is a library used to create stores that can be updated via reducers. In fact, `useSubstate` works flawlessly with your current Redux store.
102+
103+
In opposite to [react-redux][], this library only requires a `mapState` function. It is meant to call the `dispatch` function with the action directly. Advanced concepts like `connectAdvanced` or `mapDispatchToProps` are deliberately not supported.
104+
105+
To use `useSubstate` with your current [`react-redux`][] React application, find the react-redux `Provider` and make sure to wrap it with a `SubstateProvider`:
106+
107+
```diff
108+
import React from "react";
109+
import { render } from "react-dom";
110+
import { Provider } from "react-redux";
111+
+ import { SubstateProvider } from "use-substate";
112+
import { createStore } from "redux";
113+
import todoApp from "./reducers";
114+
import App from "./components/App";
115+
116+
const store = createStore(todoApp);
117+
118+
render(
119+
+ <SubstateProvider value={store}>
120+
<Provider store={store}>
121+
<App />
122+
</Provider>
123+
+ </SubstateProvider>,
124+
document.getElementById("root")
125+
);
126+
```
101127

102128
## Acknowledgements
103129

104-
Special thanks to [@gaearon](https://github.com/gaearon) and [@sophiebits](https://github.com/sophiebits) for helping me spot an issue in my initial implementation and showing me how to fix it.
130+
Special thanks to [@sophiebits](https://github.com/sophiebits) and [@gaearon](https://github.com/gaearon) for helping me spot an issue in my initial implementation and showing me how to fix it.
105131

106132
## Contributing
107133

108134
Every help on this project is greatly appreciated. To get you started, here's a quick guide on how to make good and clean pull-requests:
109135

110-
1. Create a fork of this [repository](https://github.com/philipp-spiess/use-store), so you can work on your own environment.
136+
1. Create a fork of this [repository](https://github.com/philipp-spiess/use-substate), so you can work on your own environment.
111137
2. Install development dependencies locally:
112138

113139
```bash
114-
git clone git@github.com:<your-github-name>/use-store.git
115-
cd use-store
140+
git clone git@github.com:<your-github-name>/use-substate.git
141+
cd use-substate
116142
yarn install
117143
```
118144

119145
3. Make changes using your favorite editor.
120146
4. Commit your changes ([here](https://chris.beams.io/posts/git-commit/) is a wonderful guide on how to make amazing git commits).
121-
5. After a few seconds, a button to create a pull request should be visible inside the [Pull requests](https://github.com/philipp-spiess/use-store/pulls) section.
147+
5. After a few seconds, a button to create a pull request should be visible inside the [Pull requests](https://github.com/philipp-spiess/use-substate/pulls) section.
122148

123149
## Future Improvements
124150

125-
- [ ] Find a better, more outstanding, name that also reflects what this thing is doing. (Current ideas: `useSelector`, `useReduxer`, `useGloducer`, `useStateAtom`, `useGlobalReducer`, `useShore`, `useFlux`, `useSharedState`, `useGlobalState`, `useOffShore`, `useTrunk`, `useStoreHouse`, `useDepot`)
126151
- [ ] Add Flow and TypeScript types. This is actually very important for this library: Actions must be typed as an enum such that the type system can find out if we use the wrong type.
127152
- [ ] Improve test harness.
128153

129154
## License
130155

131-
[MIT](https://github.com/philipp-spiess/use-store/blob/master/README.md)
156+
[MIT](https://github.com/philipp-spiess/use-substate/blob/master/README.md)
132157

133158
[Redux]: https://redux.js.org/introduction
134159
[react-redux]: https://github.com/reduxjs/react-redux

example/createStore.js

Lines changed: 0 additions & 23 deletions
This file was deleted.

example/example.js

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import React, { useState } from "react";
22
import ReactDOM from "react-dom";
33

4-
import "./styles.css";
5-
6-
import { createStore } from "./createStore";
7-
import { StoreProvider, useStore } from "../";
4+
import createStore from "create-state";
5+
import { SubstateProvider, useSubstate } from "../";
86

97
const initialState = { count: 0 };
108
function reducer(state, action) {
@@ -18,14 +16,14 @@ function reducer(state, action) {
1816
const store = createStore(reducer, initialState);
1917

2018
function App() {
21-
const [mappedState, dispatch] = useStore(state => {
19+
const [substate, dispatch] = useSubstate(state => {
2220
return { count: state.count };
2321
});
2422

2523
return (
2624
<div className="App">
2725
<p>
28-
<strong>{mappedState.count}</strong>
26+
<strong>{substate.count}</strong>
2927
</p>
3028

3129
<button onClick={() => dispatch({ type: "INCREMENT" })}>Increment</button>
@@ -36,8 +34,8 @@ function App() {
3634

3735
const rootElement = document.getElementById("root");
3836
ReactDOM.render(
39-
<StoreProvider value={store}>
37+
<SubstateProvider value={store}>
4038
<App />
41-
</StoreProvider>,
39+
</SubstateProvider>,
4240
rootElement
4341
);

package.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
{
2-
"name": "use-store",
2+
"name": "use-substate",
33
"version": "0.0.1",
4-
"description": "Lightweight alternative for react-redux using React Hooks",
5-
"main": "dist/use-store.js",
6-
"umd:main": "dist/use-store.umd.js",
7-
"module": "dist/use-store.m.js",
8-
"repository": "https://github.com/philipp-spiess/use-store",
4+
"description": "Subscribe to a subset of your state using using React Hooks",
5+
"main": "dist/use-substate.js",
6+
"umd:main": "dist/use-substate.umd.js",
7+
"module": "dist/use-substate.m.js",
8+
"repository": "https://github.com/philipp-spiess/use-substate",
99
"author": "Philipp Spiess",
1010
"license": "MIT",
1111
"scripts": {
12-
"build": "microbundle -o dist/ --name use-store --compress trues --sourcemap false",
12+
"build": "microbundle -o dist/ --name use-substate --compress trues --sourcemap false",
1313
"prepublishOnly": "yarn build"
1414
},
1515
"files": [

src/index.js

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,41 @@
11
import React, { useState, useContext, useEffect, useRef } from "react";
22
import shallowEqual from "./shallowEqual";
33

4-
const StoreContext = React.createContext();
4+
const SubstateContext = React.createContext();
55

6-
export const StoreProvider = StoreContext.Provider;
6+
export const SubstateProvider = SubstateContext.Provider;
77

8-
export function useStore(mapState) {
9-
const store = useContext(StoreContext);
8+
export function useSubstate(selectSubstate) {
9+
const store = useContext(SubstateContext);
1010

11-
const [mappedState, setMappedState] = useState(() => {
11+
const [substate, setSubstate] = useState(() => {
1212
const state = store.getState();
13-
return mapState(state);
13+
return selectSubstate(state);
14+
});
15+
16+
const prevSubstateRef = useRef();
17+
useEffect(() => {
18+
prevSubstateRef.current = substate;
1419
});
15-
const prevMappedStateRef = usePreviousRef(mappedState);
1620

1721
useEffect(
1822
() => {
1923
const checkForUpdates = () => {
2024
const nextState = store.getState();
21-
const nextMappedState = mapState(nextState);
25+
const nextSubstate = selectSubstate(nextState);
2226

23-
if (shallowEqual(prevMappedStateRef.current, nextMappedState)) {
27+
if (shallowEqual(prevSubstateRef.current, nextSubstate)) {
2428
return;
2529
}
2630

27-
setMappedState(nextMappedState);
31+
setSubstate(nextSubstate);
2832
};
2933
checkForUpdates();
3034

3135
return store.subscribe(checkForUpdates);
3236
},
33-
[store, mapState]
37+
[store, selectSubstate]
3438
);
3539

36-
return [mappedState, store.dispatch];
37-
}
38-
39-
function usePreviousRef(value) {
40-
const ref = useRef();
41-
useEffect(() => {
42-
ref.current = value;
43-
});
44-
return ref;
40+
return [substate, store.dispatch];
4541
}

0 commit comments

Comments
 (0)