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}

[React] Make Compound React Components Flexible的更多相关文章

  1. [React] Render Text Only Components in React 16

    In this session we create a comment component to explore how to create components that only render t ...

  2. [React] Recompose: Theme React Components Live with Context

    SASS Bootstrap allows us to configure theme or branding variables that affect all components (e.g. P ...

  3. [react] 细数 React 的原罪

    Props & onChange 的原罪 .「props & onChange 接口规范」它不是一个典型的「程序接口规范」. 当你拿到一个可视组件的 ref,却没有类似 setProp ...

  4. React笔记:React基础(2)

    1. JSX JSX是一种拥有描述UI的JavaScript扩展语法,React使用这种语法描述组件的UI. 1.1 基本语法 JSX可以嵌套多个HTML标签,可以使用大部分符号HTML规范的属性. ...

  5. react初探索--react + react-router + ant-design 后台管理系统配置

    首先确认安装了node环境,Node >= 6. 如果对react 及 ant-design 一无所知,建议去阅读下api文档,react 可以在 codePen 在线练习. react Api ...

  6. react新特性 react hooks

    本文介绍的是react新特性react hooks,本文面向的是有一定react开发经验的小伙伴,如果你对react还不是很熟悉的话我建议你先学习react并多多联系. 首先我们都知道react有3种 ...

  7. react聊天室|react+redux仿微信聊天IM实例|react仿微信界面

    一.项目概况 基于react+react-dom+react-router-dom+redux+react-redux+webpack2.0+react-photoswipe+swiper等技术混合开 ...

  8. WHAT IS THE DIFFERENCE BETWEEN REACT.JS AND REACT NATIVE?

    Amit Ashwini - 09 SEPTEMBER 2017 React.js was developed by Facebook to address its need for a dynami ...

  9. 七天接手react项目 系列 —— react 脚手架创建项目

    其他章节请看: 七天接手react项目 系列 react 脚手架创建项目 前面我们一直通过 script 的方式学习 react 基础知识,而真实项目通常是基于脚手架进行开发. 本篇首先通过 reac ...

随机推荐

  1. 拼图游戏源码-swift版项目源码

    作者fanyinan,源码PuzzleProject,公司的项目中需要一个拼图游戏,之前有手动拼图和随机打乱的功能,近期又由于个(xian)人(zhe)爱(dan)好(teng)自己加入了自动拼图功能 ...

  2. 迅为4418开发板Qt移植移动4G模块第二部分

    第一部分: http://www.cnblogs.com/topeet/p/6509248.html 第二部分: 5.ping不通域名一般是DNS没有设置对造成的.在etc下有一个文件resolv.c ...

  3. April Fools Day Contest 2019: editorial回顾补题

    A. Thanos Sort time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  4. 04C#运算符

    C#运算符 运算符分类 与C语言一样,如果按照运算符所作用的操作数个数来分,C#语言的运算符可以分为以下几种类型: l  一元运算符:一元运算符作用于一个操作数,例如:-X.++X.X--等. l  ...

  5. 小程序调用支付报错:jsapi缺少参数: total_fee

    这种情况通常是因为在调用的时候,package参数有问题导致: wx.requestPayment中package参数必须是package:"prepay_id=wx21********** ...

  6. extjs动态添加列

    可以根据日期,动态的插入一列 controller层: StdDayWordQuery:function(btn,event){ var form=Ext.getCmp('queryFormSDW') ...

  7. 诊断:RHEL7安装11.2RAC时root.sh错误ohasd failed to start

    RHEL 7.5中安装11gRAC时,在grid infrastructure的root.sh执行时,报错: # /oracle/product/11g/grid/root.sh ... Adding ...

  8. [Python3网络爬虫开发实战] 3.2.2-高级用法

    在前一节中,我们了解了requests的基本用法,如基本的GET.POST请求以及Response对象.本节中,我们再来了解下requests的一些高级用法,如文件上传.cookie设置.代理设置等. ...

  9. centos6 用户登陆管理

    查看当前登陆有哪些用户,在做什么 [root@web01 ~]# w :: up :, users, load average: 0.00, 0.00, 0.00 USER TTY FROM LOGI ...

  10. Python之协程函数

    Python之协程函数 什么是协程函数:如果一个函数内部yield的使用方法是表达式形式的话,如x=yield,那么该函数成为协程函数. def eater(name): print('%s star ...