Skip to content

Instantly share code, notes, and snippets.

@shovon
Last active January 20, 2019 04:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shovon/3c204089674743f5e80294d205e7ee1e to your computer and use it in GitHub Desktop.
Save shovon/3c204089674743f5e80294d205e7ee1e to your computer and use it in GitHub Desktop.
Redux and react-redux compatible library

Usage

// App.js

import React from "react";
import { connect } from "./state-manager-react";

const App = props => (
  <div>
    <button onClick={props.decrement}>-</button>
    {props.count}
    <button onClick={props.increment}>+</button>
  </div>
);

const mapStateToProps = state => ({
  count: state.count
});

const mapDispatchToProps = dispatch => ({
  increment: () => {
    dispatch({ type: "increment" });
  },
  decrement: () => {
    dispatch({ type: "decrement" });
  }
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(App);
// index.js

import React from "react";
import ReactDOM from "react-dom";
import App from './app';

const store = createStore((state = { count: 0 }, action = {}) => {
  switch (action.type) {
    case "increment":
      return { count: state.count + 1 };
    case "decrement":
      return { count: state.count - 1 };
  }
  return state;
});

const rootElement = document.getElementById("root");
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  rootElement
);
import React from "react";
const StateContext = React.createContext();
class ComponentProxy extends React.Component {
render() {
const NewComponent = this.props.component;
return (
<StateContext.Consumer>
{value => {
const state = value.getState();
const dispatch = value.dispatch;
const { mapStateToProps, mapDispatchToProps } = this.props;
const props = {
...this.props.props,
...mapStateToProps(state),
...mapDispatchToProps(dispatch)
};
const cb = () => {
this.forceUpdate();
value.unsubscribe(cb);
};
value.subscribe(cb);
return <NewComponent {...props} />;
}}
</StateContext.Consumer>
);
}
}
export class Provider extends React.Component {
componentDidMount() {
this.props.store.subscribe(() => {
this.forceUpdate();
});
}
render() {
return (
<StateContext.Provider value={this.props.store}>
{this.props.children}
</StateContext.Provider>
);
}
}
export function connect(mapStateToProps, mapDispatchToProps) {
return Component => {
const NewComponent = React.memo(Component);
return props => {
return (
<ComponentProxy
props={props}
component={NewComponent}
mapStateToProps={mapStateToProps}
mapDispatchToProps={mapDispatchToProps}
/>
);
};
};
}
export function createStore(reducer) {
let state = reducer();
let listeners = [];
return {
getState() {
return state;
},
dispatch(action) {
state = reducer(state, action);
listeners.forEach(listener => {
listener(state);
});
},
subscribe(callback) {
listeners = [...listeners, callback];
},
unsubscribe(callback) {
listeners = listeners.filter(listener => listener !== callback);
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment