react-bits:Children types

// You might create a component designed to apply context and render its children.

class SomeContextProvider extends React.Component {
  getChildContext() {
    return {some: "context"}
  }

  render() {
    // how best do we return `children`?
  }
}

// You’re faced with a decision. Wrap children in an extraneous <div /> or return children directly.
// The first options gives you extra markup (which can break some stylesheets). The second will result in unhelpful errors.

// option 1: extra div
return <div>{children}</div>;

// option 2: unhelpful errors
return children;

// It’s best to treat children as an opaque data type. React provides React.Children for dealing with children appropriately.
return React.Children.only(this.props.children);

// Note: We should mention that there is no API that allow us accessing child's state. Or in other words we can't use this.props.children[0].state or something like that.
// The proper way of retrieving information from the children is by using props (passing callbacks).
// And that's a good thing. This approach forces us defining clear APIs and encourage the one-way direction data flow.

// Passing a child as a property
// Every React component receive props. It's nice that these props may contain all kind of data. Even other components.

// App.jsx
class App extends React.Component {
  render() {
    var title = <h1>Hello there!</h1>;

    return (
      <Header title={ title }>
        <Navigation />
      </Header>
    );
  }
}

// Header.jsx
export default class Header extends React.Component {
  render() {
    // Note that if we don't return { this.props.children } as part of the render method the <Navigation> component will not be rendered.
    return (
      <h1>
        { this.props.title }
        <hr />
        { this.props.children }
      </h1>
    );
  }
};
// This technique is helpful when we have a mix between components that exist inside the Header and components that have to be provided from the outside.


// Using JSX Expression
function UserName(props) {
  return (
    <div>
      <b>{props.children.lastName}</b>
      {props.children.firstName}
    </div>
  );
}

function App() {
  var user = {
    firstName: 'Vasanth',lastName: 'Krishnamoorthy'
  };

  return(
    <UserName>{ user }</UserName>
  )
}

// This may look weird but may be useful in some cases. Like for example when we have some kNowledge in the parent component and don’t necessary want to send it down the tree.
// The example below prints a list of Todos.
// The App component has all the data and kNows how to determine whether a Todo is completed or not.
// The TodoList component simply encapsulate the needed HTML markup.

function TodoList(props) {
  const renderTodo = (todo,i) => {
    return (
      <li key={ i }>
        { props.children(todo) }
      </li>
    );
  };
  return (
    <section className='main-section'>
      <ul className='todo-list'>{ props.todos.map(renderTodo)}</ul>
    </section>
  );
}

function App() {
  const todos = [
    { label: 'Write tests',status: 'done' },{ label: 'Sent report',status: 'progress' },{ label: 'Answer emails',status: 'done' }
  ];
  var isCompleted = todo => todo.status === 'done';

  return (
    <TodoList todos={ todos }>
      { todo => isCompleted(todo) ? <b>{ todo.label }</b> : todo.label }
    </TodoList>
  );
}

App 组件不暴漏数据结构,TodoList不知道是否有label或status属性
当传入一个额外的prop会发生什么情况,如下:

<TodoList  todos={ todos } renderTodo= { (todo) => isCompleted(todo) ? <b>{ todo.label }</b> : todo.label
    }
  />

renderTodo更为清晰。

相关文章

react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接...
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc ...