createInverseContext.tsx 1.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. import React from "react";
  2. export const createInverseContext = <T extends unknown = null>(
  3. initialValue: T,
  4. ) => {
  5. const Context = React.createContext(initialValue) as React.Context<T> & {
  6. _updateProviderValue?: (value: T) => void;
  7. };
  8. class InverseConsumer extends React.Component {
  9. state = { value: initialValue };
  10. constructor(props: any) {
  11. super(props);
  12. Context._updateProviderValue = (value: T) => this.setState({ value });
  13. }
  14. render() {
  15. return (
  16. <Context.Provider value={this.state.value}>
  17. {this.props.children}
  18. </Context.Provider>
  19. );
  20. }
  21. }
  22. class InverseProvider extends React.Component<{ value: T }> {
  23. componentDidMount() {
  24. Context._updateProviderValue?.(this.props.value);
  25. }
  26. componentDidUpdate() {
  27. Context._updateProviderValue?.(this.props.value);
  28. }
  29. render() {
  30. return <Context.Consumer>{() => this.props.children}</Context.Consumer>;
  31. }
  32. }
  33. return {
  34. Context,
  35. Consumer: InverseConsumer,
  36. Provider: InverseProvider,
  37. };
  38. };