pcwu's TIL Notes


[React] Children 筆記

記錄一下最近用到關於 react children 的筆記,希望沒有記錯,之後有發現錯誤或新學到東西會再更新。

Intro

React 元件內有一個東西叫 children,代表該元件被給予的子元件,舉個例子:

const ChildA = ({ name }) => (
  <h1>{`Hello ${name}`}</h1>
);

const Parent = () => (
  <div style={somestyle}>
    <Something />
    <div>
      {children}
    </div>
    <OtherThings />
  </div>
);

const Container = () => (
  <div>
    <Parent>
      <ChildA name={name}/>
    </Parent>
  </div>
);

可以看得出來在 renderParent 會拿到 ChildA 並把它放在 {children} 這個位置。如果不使用的話,就變成要 ContainerParent 再套 ChildA 了,但這樣的話 Parent 就無法被很好的重覆利用,一但套的 ChildA 換成 ChildX 就變成要產生新的元件了。

Parent 如何給 Children Props?

前面例子,ChildA 拿到的 name 是直接從 Container 拿到的(這邊:<ChildA name={name}/>),但如果我們有些事情是到了 Parent 這邊才確定的話,要如何傳給 ChildA 呢?

以下是我發現的解決方法,但感覺可能有更直接的:

Looping on Children Components

this.props.children 雖然是指子元件「們」,但並不是一個可以拿來用 map 一個一個拿出來的,所以 React 提供了一個方法叫 React.Children,可以透過 React.Children.map() 來一個一個將 children 取出使用。

從 Parent 提供 props

Parent 可以透過 React 提供的 React.cloneElement 來給予 children 所需的 props 或給予它 children。但既然叫 cloneElement 應該不難想像其實是像 ES6 的 Object.assign()

ReactElement cloneElement(
  ReactElement element,
  [object props],
  [children ...]
)

React.Children.map() 搭配 React.cloneElement

所以結合起來使用,就變成像這個例子,可以進行一些判斷並給予 props

function renderChildren(props) {
  return React.Children.map(props.children, child => {
    if (child.type === RadioOption)
      return React.cloneElement(child, {
        name: props.name
      })
    else
      return child
  })
}

Reference