function A({children}){
????console.log("A");
????const [state, setState]=useState(0);
????useEffect(()=>{
????????setState((state)=>state+1);
????},[]);
????return children;
}
/* Here even on state change of `A` parent component, child components will not re-render. When the parent state changes, parent component re-renders. But it still has the?same children prop?it got last time, so React doesn’t visit that subtree. And as a result, child component doesn’t re-render.
?Thus there are two ways to prevent child components from re-rendering.
? ? - wrapping them in `memo`
? ? - passing them as `children` prop
*/
In JSX expressions,?the content between an opening and closing tag is passed as a unique prop called children. There are several ways to pass children, such as rendering string literals or using JSX elements and JavaScript expressions. It is also essential to understand the types of JavaScript values that are ignored as children and don’t render anything.
Types of Children
String literals
String literals refer to simple JavaScript strings. They can be put between the opening and closing tags, and the children prop will be that string.
<MyComponent>Little Lemon</MyComponent>
In the above example, the children prop in MyComponent will be simply the string “Little Lemon”.?
JSX Elements
JavaScript Expressions
You can pass any JavaScript expression as children by enclosing it within curly braces, {}.
function?Dessert(props)?{
??return?<li>{props.title}</li>;
}
function?List()?{
??const?desserts?=?['tiramisu',?'ice?cream',?'cake'];
??return?(
????<ul>
??????{desserts.map((dessert)?=>?<Item?key={dessert}?title={dessert}?/>)}
????</ul>
??);
}
Functions
Suppose you insert a JavaScript expression inside JSX. In that case, React will evaluate it to a string, a React element, or a combination of the two. However, the children prop works just like any other prop, meaning it can be used to pass any type of data, like functions.
Function as children is a React pattern used to abstract shared functionality that you will see in detail in the next lesson.
Booleans, Null and Undefined, are ignored
false, null, undefined, and true are all valid children. They simply don’t render anything. The below expressions will all render the same thing:
<div />
<div></div>
<div>{false}</div>
<div>{null}</div>
<div>{undefined}</div>
<div>{true}</div>
Again, this is all for demonstration purposes so that you know what to expect on your screen when these special values are used in your JSX.?
When used in isolation, they don’t offer any value. However, boolean values like true and false can be useful to conditionally render React elements, like rendering a Modal component only if the variable showModal is true:
<div>
??{showModal?&&?<Modal?/>}
</div>
However, keep in mind that React still renders some "false" values, like the 0 number. For example, the below code will not behave as you may expect because 0 will be printed when props.desserts is an empty array:
<div>
??{props.desserts.length?&&
????<DessertList?desserts={props.desserts}?/>
??}
</div>
To fix this, you need to make sure the expression before && is always boolean:
<div>
??{props.desserts.length?>?0?&&
????<DessertList?desserts={props.desserts}?/>
??}
</div>
<div>
??{!!props.desserts.length?&&
????<DessertList?desserts={props.desserts}?/>
??}
</div>
The children prop which is a special property all components have, is the foundation for the React powerful composition model.?
上层组件传下的属性,下层组件无法提前预知,但依然可以组合
function?Bag(props)?{
????const?bag?=?{
????????padding:?"20px",
????????border:?"1px?solid?gray",
????????background:?"#fff",
????????margin:?"20px?0"
????}
????return?(
????????<div?style={bag}>
????????????{props.children}
????????</div>
????)
}
export?default?Bag
There are two main features that enable component composition; containment and specialization.?
Containment refers to the fact that some components don't know their children ahead of time.?
This is especially common for components like a sidebar or a dialog, where they delimit a specific area in your UI to contain other elements. You can think of them also as generic boxes.?
In case you don't know, a dialog is a type of modal window where the rest of the UI is disabled until the modal is addressed and interacted with.?
For these component boxes, the recommended approach is to use the children prop to pass children elements directly as their content.?
Let's explore this with a dialog example.?
Here you have a dialog component which acts as the box, taking care of styling the container to make it look like a modal window. By using the children prop, it has become a generic component to which we can provide any valid JSX as children.?
To illustrate that, the confirmation dialog component has been defined, which uses the dialog component and renders as children a title and a description.?
This example also showcases the second feature of component composition, specialization. Specialization defines components as being special cases of other components. In this example, the confirmation dialog is a special case of dialog.
But what is this props.children
<Example>
????Hello?there
</Example>
The Hello there text is a child of the Example JSX element. The Example JSX Element above is an "invocation" of the Example.js file, which, in modern React, is usually a function component.
Now, did you know that this Hello there piece of text can be passed as a named prop when rendering the Example component
Here's how that would look like:
<Example?children="Hello?there"?/>
Ok, so, there are two ways to do it. But this is just the beginning.
What if you, say, wanted to surround the Hello there text in an h3 HTML element
Obviously, in JSX, that is easily achievable:
<Example?children={<h3>Hello?there</h3>}?/>
What if the <h3>Hello there</h3> was a separate component, for example, named Hello
In that case, you'd have to update the code like this:
<Example?children={<Hello?/>}?/>
You could even make the Hello component more dynamic, by giving it its own prop:
<Example?children={<Hello?message="Hello?there"?/>}?/>
In JS, B is a function. B will only evaluate when we call it.?B()
We are passing B?function?in A. It will pass without running.
When we return?children?react will execute the B.
props.children.map函数来遍历会收到异常提示,为什么?应该如何遍历?
this.props.children的值有三种可能:
1.当前组件没有子节点,它是undefined;
2.有一个子节点,数据类型是object ;
3.有多个子节点,数据类型就是array 。
react提供React.Children.map(children, callback)安全的遍历子节点