I. Warehouse address

This article, based on [email protected], explains how I used the new Context API for tool injection. Making the address

Why inject tools into components

For example, in a component tree, it is common for multiple components to use Ajax to request data from the server. In this case, you must introduce Ajax-related libraries in each component to use them, as follows:

import ajax from 'ajax'

export default class App extends Component {
  ...

  componentDidMount () {
    ajax.get('http://xxx.com/a') .then(res => { ... })}... }Copy the code

And because each component has a different dependency on the tool, there are quite a few library introduction statements.

// a.jsx
import ajax from 'ajax'

//b.jsx
import ajax from 'ajax'
import storage from 'storage'
Copy the code

However, I don’t want to introduce the basic tools to each component when I need them. For the react project with multiple entrances, can we store the tools at the top of the component tree at the entrance and inject the top tools into the corresponding sub-components when necessary? Then use this to access the corresponding tool to use

Import {injectMethods} from; import {injectMethods} from; import {injectMethods} from'provider'

@injectMethods
export default class TestProvider extends Component {
  ...

  componentDidMount () {
    this.props.ajax.get('http://xxx.com/a')
      .then(res => {
          ...
      })

    this.props.storage.setItem('key'.'value')}... }Copy the code

This way, we don’t need to worry about the introduction of tools for components, and manage them all at the top level, but you can also inject the rest of the global properties

Three, implementation,

React uses the React Context API declaratively. Here’s how to use the React Context API declaratively

// entry js // Provider webpack is definedalias
import { setProvider } from 'provider'
import detectAgent from 'provider/detect-agent'
import dateFormat from 'provider/format/date-format'
import storage from 'provider/storage'
import urlutils from 'provider/url-utils'// The top layer needs the injection methodletProviders = object. assign({}, detectAgent, dateFormat, storage, urlutils) render(// context. ProvidersetProvider(App, providers),
  document.getElementById('app'))Copy the code
// provider/index.js

exportConst Context = react.createcontext () // Pass in the root node and the base tool and wrap the component with context.providerexport const setProvider = (RootComponent, providers) => {
  return(< context.provider value={providers}> <RootComponent></RootComponent> </ context.provider >)} /** * inject global methods into child components by annotating @ @param {component} RealComponent * * InjectMethods * class TestComponent extends Component {} * * this is a way to injectMethods stored at the top level into the props property of the Component */export const injectMethods = (RealComponent) => {
  return class extends Component {
    render () {
      return( <Context.Consumer> { value => <RealComponent {... value} {... this.props}></RealComponent> } </Context.Consumer> ) } } }Copy the code

In the entry file, we place the methods in the context. Provider component. Then we use the context. Consumer component to get the value stored in the Provider and inject the tool into the props of the child component. InjectMethods is an annotation. If you have a component that needs to access top-level tools, annotate the component directly and inject it into props

import { injectMethods } from 'provider'// Inject the top-level method @injectMethods into TestProvider propsexport default class TestProvider extends Component {
  componentDidMount() {// Any component can use injectMethods to inject console.log()'test-provider has injected global methods into props')
    console.log(this.props)
  }

  render () {
    let { $dateFormat } = this.props;

    return (
      <div>
        <p>test-provider</p>
        <p>{ $dateFormat(new Date()) }</p>
      </div>
    )
  }
}
Copy the code

Of course, this approach also allows for unified management of constants in the component tree, which can be injected into props as needed.