美文网首页让前端飞
React Tips: 依赖注入、全局包裹Context

React Tips: 依赖注入、全局包裹Context

作者: coolheadedY | 来源:发表于2018-03-23 17:33 被阅读350次

依赖注入

props 传递

  • props 层层传递
  • 很多组件并不需要使用 props
  • 不推荐
// Title.jsx
export default function Title(props) {
  return <h1>{ props.title }</h1>;
}
// Header.jsx
import Title from './Title.jsx';
export default function Header() {
  return (
    <header>
      <Title />
    </header>
  );
}
// App.jsx
import Header from './Header.jsx';
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { title: 'React Dependency Injection' };
  }
  render() {
    return <Header />;
  }
}

HOC 高阶组件

// title.jsx
import React from 'react'

export default function Title(props) {
  return <h1>{ props.title }</h1>
}
// inject.jsx
import React from 'react'
export default function inject(Component) {
  return class Injector extends React.Component {
    render() {
      const { title } = this.props
      return (
        <Component
          {...this.state}
          {...this.props}
          {...this.children}
          title={ title }
        />
      )
    }
  }
}
// header.jsx
import React from 'react'
import inject from './inject'
import Title from './title'

const title = 'React Dependency Injection'
const EnhancedTitle = inject(Title)

export default function Header() {
  return (
    <header>
      <EnhancedTitle title={title} />
    </header>
  )
}

新版 Context API

// title.jsx
import React from 'react'
import { InjectContext } from './inject'

export default class Title extends React.Component {
  render() {
    return (
      <InjectContext.Consumer>
        {context => (
          <div>
            {console.log(context)}
            <h1>{context.title}</h1>
          </div>
        )}
      </InjectContext.Consumer>
    )
  }
}
// inject.jsx
import React from 'react'
export const InjectContext = React.createContext({})
// header.jsx
import React from 'react'
import Title from './title'
export default class Header extends React.Component {
  render() {
    return <Title />
  }
}
// App.js
import React, { Component } from 'react';
import Header from './header'
import { InjectContext } from './inject'

class App extends Component {
  render() {
    return (
      <InjectContext.Provider value={{ title: 'React Dependency Injection' }}>
        <Header />
      </InjectContext.Provider>
    );
  }
}

export default App;

全局包裹Context

新版Context API 实现

相比于单纯的数据对象,将context包装成一个提供一些方法的对象会是更好的实践。因为这样能提供一些方法供我们操作context里面的数据。

// dependcies.js
export default {
  data: {},
  get(key) {
    return this.data[key];
  },
  register(key, value) {
    this.data[key] = value;
  }
}
// header.jsx
import React from 'react'
import Title from './title.jsx'

export default function Header() {
  return (
    <header>
      <Title />
    </header>
  )
}
// inject.js
import React from 'react'

export const InjectContext = React.createContext({})

创建dependcies后可以用dependencies.register 注册数据

// App.js
import React, { Component } from 'react';

import dependencies from './dependencies'
import Header from './header'
import { InjectContext } from './inject'
dependencies.register('title', 'context-react-patterns')

class App extends Component {
  render() {
    return (
      <InjectContext.Provider value={dependencies}>
        <Header />
      </InjectContext.Provider>
    )
  }
}

export default App;

然后在 Title 组件中直接从 Context 获取数据

import React from 'react'
import { InjectContext } from './inject'

export default class Title extends React.Component {
  render() {
    return (
      <InjectContext.Consumer>
        {context => (
          <div>
            <h1>{context.get('title')}</h1>
          </div>
        )}
      </InjectContext.Consumer>
    )
  }
}

高阶组件 HOC 实现

// dependencies.jsx
import React from 'react'

let dependencies = {}

export function register(key, dependency) {
  dependencies[key] = dependency
}

export function fetch(key) {
  if (dependencies.hasOwnProperty(key)) return dependencies[key]
  throw new Error(`"${ key } is not registered as dependency.`)
}

export function wire(Component, deps, mapper) {

  return class Injector extends React.Component {
    constructor(props) {
      super(props)
      this._resolvedDependencies = mapper(...deps.map(fetch))
    }

    render() {
      return (
        <Component
          {...this.state}
          {...this.props}
          {...this._resolvedDependencies} // {title: "react-patterns"}
        />
      )
    }
  }
}

在App 组件中使用register 注册数据

// App.js
import React, { Component } from 'react';

import Header from './header'
import { register } from './dependencies'
register('awesome-title', 'HOC-react-patterns')

class App extends Component {
  render() {
    return <Header />
  }
}

export default App;

// header.jsx
import React from 'react'
import Title from './title.jsx'

export default function Header() {
  return (
    <header>
      <Title />
    </header>
  )
}

在 Title 组件中通过 wire 注入数据

// title.jsx
import React from 'react'
import { wire } from './dependencies'

const Title = props => (<h1>{ props.title }</h1>)

export default wire(Title, ['awesome-title'], title => ({ title }))

相关文章

  • React Tips: 依赖注入、全局包裹Context

    依赖注入 props 传递 props 层层传递很多组件并不需要使用 props不推荐 HOC 高阶组件 新版 C...

  • React 拾遗之 Context

    React 拾遗之 Context React.js 的 context 其实像就是组件树上某颗子树的全局变量 使...

  • vue2升级vue3注意事项

    vite兼容 require.context 替换成import.meta.globEager scss 全局注入...

  • springboot中使用缓存shiro-ehcache

    在pom.xml中注入缓存依赖,版本(Sep 09, 2016)spring-context-support包含支...

  • Android全局Context

    Android 全局Context 继承Application类 注册全局Context类

  • 2018-08-08

    React 高级指南 React 新版上下文(context) context ?答:上下文(Context) 提...

  • Context

    在一个组件树中共享“全局”的数据 React.createContext 创建一个 Context 对象。当 Re...

  • React-redux

    React-redux 底层:通过高阶组件 + context跨组件传值实现,用 包裹根元素, 解决了在组件中频繁...

  • .NET Core 依赖注入改造(5)- Context

    .NET Core 依赖注入改造(1)- 命名服务.NET Core 依赖注入改造(2)- 委托转换.NET Co...

  • 全局Context

    全局Context 在许多方法执行的时候,都需要context做为参数。当你自己封装工具类等很多时候,你会获取不到...

网友评论

    本文标题:React Tips: 依赖注入、全局包裹Context

    本文链接:https://www.haomeiwen.com/subject/hcztcftx.html