{"id":13781137,"url":"https://github.com/xnimorz/react-providers","last_synced_at":"2025-03-22T11:30:47.221Z","repository":{"id":39493619,"uuid":"143775152","full_name":"xnimorz/react-providers","owner":"xnimorz","description":"The React Component, which allows you to combine contexts and incapsulate to components using HOC, is built on a top of Context API","archived":false,"fork":false,"pushed_at":"2023-01-07T07:04:25.000Z","size":3605,"stargazers_count":23,"open_issues_count":37,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-18T10:46:30.517Z","etag":null,"topics":["context","context-provider","react","react-context","react-context-api","reactjs","state-management","state-manager"],"latest_commit_sha":null,"homepage":"https://xnimorz.github.io/react-providers/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xnimorz.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-08-06T19:44:21.000Z","updated_at":"2024-09-02T21:22:05.000Z","dependencies_parsed_at":"2023-02-06T14:31:10.054Z","dependency_job_id":null,"html_url":"https://github.com/xnimorz/react-providers","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xnimorz%2Freact-providers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xnimorz%2Freact-providers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xnimorz%2Freact-providers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xnimorz%2Freact-providers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xnimorz","download_url":"https://codeload.github.com/xnimorz/react-providers/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244951100,"owners_count":20537319,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["context","context-provider","react","react-context","react-context-api","reactjs","state-management","state-manager"],"created_at":"2024-08-03T18:01:23.321Z","updated_at":"2025-03-22T11:30:46.597Z","avatar_url":"https://github.com/xnimorz.png","language":"TypeScript","funding_links":[],"categories":["List","Libraries"],"sub_categories":[],"readme":"# react-providers\n\nReact-providers is a library which helps you to work and manage React.Context components. The library offers you:\n\n- simple syntax with HOC components like react-redux.connect;\n- the single location to place your context models;\n- to implement your own business logic in contexts using familiar React components and react-lifecycle methods;\n- an easy way to include another context when it became required;\n- to work with dependencies between your contexts. So you should just describe dependencies and react-providers will build a correct hierarchy for you. You can see comments example to get more information about managing dependencies;\n- working both in server and client\n- this library depends only on `hoist-non-react-statics`, so you wouldn't get a lot of npm modules after installing.\n\n## Contents\n\n- [Demo](#demo)\n- [Install](#install)\n- [Usage step by step](#usage-step-by-step)\n  - [Using only a HOC for context](#using-only-a-hoc-for-context)\n  - [Working with the store and connect to it](#working-with-the-store-and-connect-to-it)\n- [Developer experience](#developer-experience)\n  - [Why I should use react-providers instead of plain react.Context?](#why-i-should-use-react-providers-instead-of-plain-react.context)\n  - [About react-providers pros](#about-react-providers-pros)\n  - [About redux](#about-redux)\n  - [How to work without redux and any other library. Just using react](#how-to-work-without-redux-and-any-other-library.-Just-using-react)\n- [Dependencies resolver](#dependencies-resolver)\n- [License](#License)\n\n### Demo\n\nHere is several examples: https://xnimorz.github.io/react-providers/\n\n## Install\n\n```\nyarn add react-providers\n```\n\nor\n\n```\nnpm install --save react-providers\n```\n\n## Usage step by step\n\nThis library can work in two mods:\n\n1. Use only HOC for Context\n2. Create the store with lots of context components\n\nLet's see how to use library in both ways\n\n### Using only a HOC for context\n\n1. Implement your own React.Component using React.Context or just using React.Context:\n\n```javascript\nexport const TodosContext = React.createContext(['Do some work', 'Close task in jira']);\n```\n\n2. Connect to this context using HOC `use`:\n\n```javascript\nimport { TodosContext } from './path/to/TodosContext';\n\nfunction MyComponent({ todos }) {\n  console.log(todos); // ['Do some work', 'Close task in jira']\n}\n\nexport default use({ todos: TodosContext })(MyComponent);\n```\n\n### Working with the store and connect to it\n\n#### Step 1: Create your context React component:\n\nImplement your own React.Component using React.Context:\n\nhttps://github.com/xnimorz/react-providers/blob/master/examples/src/models/todoMVC/todos.js — in this file we use React lifecycle methods to store updates in localStorage.\n\n```javascript\nimport React from 'react';\n\nconst TodosContext = React.createContext();\nclass TodosContextProvider extends React.Component {\n  state = {\n    list: lsData || [],\n  };\n  // We can use React lifecycle methods to organise our work!\n  componentDidUpdate() {}\n\n  // You can get access to the methods from context consumer\n  // This methods like reducers in Redux changes the state of the application but using React api\n  add = (todo) =\u003e {\n    this.setState((state) =\u003e ({\n        list: [\n          ...state.list,\n          { id: 1 + Math.max(0, ...state.list.map((todo) =\u003e todo.id)), text: todo, completed: false },\n        ],\n      },\n    }));\n  };\n\n  render() {\n    // describe data that will be Context.Provider value (we can use here memoization, or move it to state to avoid unnecessary rerenders)\n    const value = {\n      // our data\n      data: this.state,\n      // our methods\n      add: this.add,\n    };\n\n    // Provide value to consumer\n    return \u003cTodosContext.Provider value={value}\u003e{this.props.children}\u003c/TodosContext.Provider\u003e;\n  }\n}\n\n// Each module should provide 2 components — Consumer and Provider\nexport default {\n  Consumer: TodosContext.Consumer,\n  Provider: TodosContextProvider,\n};\n```\n\n#### Step 2: Add the context to react-providers.AppProvider:\n\nThen, you can add your providers to the AppProvider:\n\n```javascript\nimport React from 'react';\nimport reactDOM from 'react-dom';\nimport { AppProvider } from 'react-providers';\nimport todos from './path/to/todos';\n\nreactDOM.render(\n  \u003cAppProvider contexts={{ todos }}\u003e\n    \u003cExample\u003e\n      YourApplicationIsHere\n    \u003c/Example\u003e\n  \u003cAppProvider/\u003e\n);\n```\n\n#### Step 3: Getting access to data from the context\n\nWe can use `use` HOC to get access to data that we store with `AppProvider` component:\n\n```javascript\nimport React from 'react';\nimport { use } from 'react-providers';\nimport todos from './path/to/todos';\n\nclass Example extends React.Component {\n  componentDidMount() {\n    // We'll get access to methods\n    this.props.todos.add('New todo');\n  }\n  render() {\n    // And data\n    console.log(this.props.todos.data.list); // first time we'll get [], and second time [{id: 1, text: 'New todo', completed: false}]\n    return 'SomeData';\n  }\n}\n\nexport default use({ todos })(Example);\n```\n\nSee more examples here: https://xnimorz.github.io/react-providers/\n\n#### Step 4 (optional): create context which depends on another context\n\n`AppProvider` automatically builds correct Context tree that resolves dependencies between contexts. To get access from one context to another you can use `use` HOC:\n\n```javascript\nimport React from 'react';\nimport { AppProvider, use } from 'react-providers';\n\nconst A = React.createContext({});\nclass AProvider extends React.Component\u003c{}, { data: string }\u003e {\n  state: Readonly\u003c{ data: string }\u003e = {\n    data: 'A Context',\n  };\n\n  render() {\n    return \u003cA.Provider value={this.state}\u003e{this.props.children}\u003c/A.Provider\u003e;\n  }\n}\n\nconst aContext: IContext = {\n  Consumer: A.Consumer,\n  Provider: AProvider,\n};\n\nconst B = React.createContext({});\nclass BProvider extends React.Component\u003c{}, { data: string }\u003e {\n  state: Readonly\u003c{ data: string }\u003e = {\n    data: 'B Context',\n  };\n\n  render() {\n    console.log(this.props.a.data); // 'A Context'\n\n    return \u003cB.Provider value={this.state}\u003e{this.props.children}\u003c/B.Provider\u003e;\n  }\n}\n\nconst bContext: IContext = {\n  Consumer: B.Consumer,\n  // Describe BContext depends on AContext\n  Provider: use('a')(BProvider),\n};\n\nReactDOM.render(\u003cAppProvider contexts={{ a: aContext, b: bContext }} /\u003e);\n```\n\n## Developer experience\n\n### Why I should use react-providers instead of plain react.Context?\n\n1. The centralised place to store and manage our logic\n\nYou can store your context in one place where you paste AppProvider component (as a rule, it's better to put it at the beginning of React tree).\nYou won't spend the time to manage dependencies between components. it's enough to declare dependency using `use` HOC in Providers (like in examples above). You have only one limitation — cyclic dependencies aren't allowed.\n\n2. Reduce code wrapping\n\nAs a rule, each model, which presented by React.Context component, should have only a single responsibility (SOLID principles). In our React components, we often want to get data from several Consumers. In such cases our code would be:\n\n```javascript\nfunction YourComponent() {\n  return (\n    \u003cUsersConsumer\u003e\n      {(users) =\u003e\n        \u003cTopicsConsumer\u003e\n          {(topics) =\u003e\n            \u003cCommentsConsumer\u003e{(comments) =\u003e /*Your data*/ }\u003c/CommentsConsumer\u003e\n          }\n        \u003c/TopicsConsumer\u003e\n      }\n    \u003c/UsersConsumer\u003e\n  );\n}\nexport default YourComponent;\n```\n\nLet's compare this example to the same example with react-providers lib:\n\n```javascript\nfunction YourComponent() {\n  const { users, topics, comments } = this.props;\n  return (/*Your data*/);\n}\n// 1) connection using Object:\nexport default use({\n  users: UserContext,\n  topics: TopicsContext,\n  comments: CommentsContext\n})(YourComponent)));\n// 2) or using array:\nexport default use('users', 'topics', 'comments')(YourComponent)));\n```\n\nWe encapsulated all consumers' logic to our HOC component `use`. In component, we paid attention to _How our component should work and what data it should return_.\n\n### About react-providers pros\n\nReact-providers works with React.Context and offers you an easy way to combine and to store Contexts in one place. You work with familiar Components state. It hasn't any additional boilerplate code.\nReact-providers manage your dependencies between contexts, so you don't mind about the right order of contexts in React components tree.\nHOC `use` allows you to describe dependencies using objects, arrays or string.\n\n### About redux\n\nRedux (https://github.com/reduxjs/redux) is a great library that offers you time traveling and to store all application data in one place. It uses actions to describe what happens in application and reducers to implement the data logic of your application. To implement async action creators we can use our own middleware or existed middleware like redux-saga or redux-thunk. Redux offers us a great and pretty clear API to build our applications.\nBut we'll have lots of boilerplate code to describe all actions, reducers etc. If you create not a too big application you probably don't need redux.\n\n### How to work without redux and any other library. Just using react\n\nOn the other hand, you probably don't need redux. Our React components can work without redux. And they do work.\nWe can implement a method `addTodo` to the React component called `Todos`, which adds a new todo to the list that stored in the component state. Then we can transfer this `addTodo` method as a prop to other components. By this way, components can call `addTodo`.\nIn described case `addTodo` calls `this.setState` method to set a new state to our `Todos` React component. _`addTodo` implements the reducer pattern in our application._ So `addTodo` is pretty similar to reducers in Redux. Moreover, react.lifecycle methods offer you to implement middlewares logic in react. You can add you own logic to componentDidMount, DidUpdate etc. methods. Consequently, we can work using only React API and React boilerplates to implement both view and business logic, because React already has methods that you need to implement your business logic.\n\nLet's have a look at the way how we can work without redux:\n\n1. We can implement our business or async logic locally using React components. To transfer data from one component to another we can use props.\n2. When or if this logic becomes necessary in several places in our application we can move it to React Context.\n3. When one context depends on another context we can decompose them and place them in the correct order in React components tree.\n\nOR\n\nWhen we realize the logic becomes necessary in several places in our app we can move it to React Context and put it to react-providers.AppProvider component. And now we won't mind about where we should add Consumer for context. We just use `use` HOC where we need like react-redux.connect.\n\n## Dependencies resolver\n\nThis library resolves automatically dependencies between Providers. It means you can create two contexts AContext and BContext. BContext can depend on AContext, and the application will work correctly.\n\nThe main limitation is you should create cyclic dependencies. e.g. BContext can depend on AContext, but AContext can't depend on BContext simultaneously.\n\n## License\n\nMIT License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxnimorz%2Freact-providers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxnimorz%2Freact-providers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxnimorz%2Freact-providers/lists"}