zoukankan      html  css  js  c++  java
  • [React] Make Compound React Components Flexible

    Our current compound component implementation is great, but it's limited in that users cannot render the structure they need. Let's allow the user to have more flexibility by using React context to share the implicit state to our child <Toggle/> components. We will walk through using React's official context API with React.createContext and use the given Provider and Consumer components to share state implicitly between our compound components giving our users the flexibility they need out of our component.

    When we use compound component, we are also using React.Children.map:

        return React.Children.map(this.props.children, child => {
          return React.cloneElement(child, {
            on: this.state.on,
            toggle: this.toggle,
          })
        })

    React.Children.map + this.props.children limits what compound compoment should found some structure, you can do:

      return (
        <Toggle onToggle={onToggle}>
          <Toggle.On>The button is on</Toggle.On>
          <Toggle.Button />
          <Toggle.Off>The button is off</Toggle.Off>
        </Toggle>
      )

    But app will break if you do:

      return (
        <Toggle onToggle={onToggle}>
          <Toggle.On>The button is on</Toggle.On>
          <Toggle.Button />
          <div>
             <Toggle.Off>The button is off</Toggle.Off>
          </div>
        </Toggle>
      )    

    Because this.props.children will looking for direct child inside <Toggle>, if we add <div> wrapper, it will break the structure, then code won't work.

    So we need more flexable code, to achieve that we can use Context.

    // Flexible Compound Components with context
    
    import React from 'react'
    import {Switch} from '../switch'
    
    const ToggleContext = React.createContext()
    
    class Toggle extends React.Component {
    
      static On = ({children}) => (
        <ToggleContext.Consumer>
          {contextValue => (contextValue.on ? children : null)}
        </ToggleContext.Consumer>
      )
      static Off = ({children}) => (
        <ToggleContext.Consumer>
          {contextValue => (contextValue.on ? null : children)}
        </ToggleContext.Consumer>
      )
      static Button = props => (
        <ToggleContext.Consumer>
          {contextValue => (
            <Switch
              on={contextValue.on}
              onClick={contextValue.toggle}
              {...props}
            />
          )}
        </ToggleContext.Consumer>
      )
      state = {on: false}
      toggle = () =>
        this.setState(
          ({on}) => ({on: !on}),
          () => this.props.onToggle(this.state.on),
        )
      render() {
    
        return (
          <ToggleContext.Provider
            value={{
              on: this.state.on,
              toggle: this.toggle,
            }}
          >
            {this.props.children}
          </ToggleContext.Provider>
        )
      }
    }
    
    function Usage({
      onToggle = (...args) => console.log('onToggle', ...args),
    }) {
      return (
        <Toggle onToggle={onToggle}>
          <Toggle.On>The button is on</Toggle.On>
          <Toggle.Off>The button is off</Toggle.Off>
          <div>
            <Toggle.Button />
          </div>
        </Toggle>
      )
    }
    Usage.title = 'Flexible Compound Components'
    
    export {Toggle, Usage as default}
  • 相关阅读:
    导入旧版本Android项目时的“Unable to resolve target ‘android
    eclipse打开文件目录
    ireport常见问题
    【技术贴】解决127.0.0.1和http://localhost均被拦截跳转到另一个网页
    【技术贴】SqlServer2008 R2 安装失败提示出现以下错误 服务 MSSQLSERVERO
    【技术贴】解决xp下Microsoft.SqlServer.Management.PSProvider.dll
    websphere性能设置和日常维护
    【技术贴】解决支付宝充值信用卡还款跳转到网上银行报错Error 404
    jQuery制作Facebook Timeline时间轴
    借助rownum中求Oracle表中前三名(三甲:状元榜眼探花)的方法(总计三种方法,以讲述rownum的使用为主)
  • 原文地址:https://www.cnblogs.com/Answer1215/p/9542114.html
Copyright © 2011-2022 走看看