Skip to content

Instantly share code, notes, and snippets.

@erodactyl
Last active February 25, 2019 11:22
Show Gist options
  • Save erodactyl/d20284d05357570ce828b97b8c297339 to your computer and use it in GitHub Desktop.
Save erodactyl/d20284d05357570ce828b97b8c297339 to your computer and use it in GitHub Desktop.
Context API implementation
import React from 'react';
const createContext = (defaultState = undefined) => {
let state = defaultState;
let subscribers = [];
const subscribe = cb => {
// We call this function ourselves so no need to check the typeof cb === 'function'
subscribers.push(cb);
return () => {
subscribers = subscribers.filter(c => c !== cb);
};
};
const setState = value => {
state = value;
// Ping subscribers to let them know they need to rerender
subscribers.forEach(cb => cb());
};
// Rerendering the Provider is expensive, need to use PureComponent to avoid unnecessary renders
class Provider extends React.PureComponent {
componentWillMount() {
setState(this.props.value);
}
componentWillUpdate({ value }) {
setState(value);
}
render() {
return this.props.children;
}
}
const Consumer = ({ children }) => {
const [, setValue] = React.useState(true);
React.useEffect(() => {
// This "forceUpdate" callback is created only once, so no performance bottleneck
return subscribe(() => setValue(s => !s));
}, []);
if (state === undefined) {
return null;
}
return children(state);
};
return { Provider, Consumer };
};
export default createContext;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment