// 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更为清晰。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。