component composition with props

2023-09-06  本文已影响0人  Time_Notes

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. 

containment example: dialog无法提前预知props.children

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. 

children composition

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)安全的遍历子节点

上一篇下一篇

猜你喜欢

热点阅读