Skip to content

⚛️ A react utility function to decorate a component with context, similar to how react-redux works

License

Notifications You must be signed in to change notification settings

Swiggy/react-context-decorator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@swiggy/react-context-decorator

A React utility function to decorate a component with context, similar to how react-redux works.

You might want to look into upcoming experimental useContext React Hook which might solve the problem in much more elegant way.

Installation

npm install @swiggy/react-context-decorator

Motivation

While render props pattern is a cool way to get data out from a Component, it can be quite messy to use. Higher Order Components tend to keep code less messy, but have their own issues. However, we feel that it would've been a nightmare if Redux never shipped with connect (part of react-redux) and asked the user to rely on Render props everywhere. Similar to connect, decorateWithContext makes it easier to mapContextToProps and escape from render prop hell.

Usage

View on CodeSandbox.

import React from "react";
import ReactDOM from "react-dom";
import { decorateWithContext } from "@swiggy/react-context-decorator";

/*
This is how our component heirarchy is

<App /> (has the context value) 
|
|_<Content />
  |
  |_<Profile />
      |
      |_<MyGreeting />
      |  |
      |  |_<Greeting /> (context.name -> props.name)
      |
      |_<MyAge />
        |
        |_<Age /> (context.age -> props.age)

Instead of passing props from App -> Content -> Profile -> Greeting,
we would make use of React's context API to directly pass it from App to Greeting.
*/

// Create context using new Context API
const MyContext = React.createContext({ name: "", age: 0 });

// Decorate with `MyContext`
const withMyContext = decorateWithContext(MyContext);

// Your Component that would receive context value in props
const Greeting = props => <h1>Hello {props.name}!</h1>;

// Pick `name` from the context
const withName = withMyContext(context => ({ name: context.name }));

// Decorated component
const MyGreeting = withName(Greeting);

// Your Component that would receive context value in props
const Age = props => <p>Your age is {props.age}.</p>;

// Pick `age` from the context
const withAge = withMyContext(context => ({ age: context.age }));

// Decorated component
const MyAge = withAge(Age);

const Profile = props => (
  <React.Fragment>
    <MyGreeting />
    <MyAge />
  </React.Fragment>
);

const Content = props => (
  <div>
    <Profile />
  </div>
);

class App extends React.PureComponent {
  state = {
    age: 0,
    name: ""
  };

  render() {
    return (
      <MyContext.Provider value={this.state}>
        <input
          type="text"
          placeholder="Enter your name"
          value={this.state.value}
          onChange={e => this.setState({ name: e.target.value })}
        />
        <input
          type="number"
          placeholder="Enter your age"
          value={this.state.age}
          onChange={e => this.setState({ age: e.target.value })}
        />
        <Content />
      </MyContext.Provider>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Contributions

Feel free to report issues or raise pull requests.

About

⚛️ A react utility function to decorate a component with context, similar to how react-redux works

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published