среда, 26 октября 2022 г.

React Extend Children Props | React cloneElement

 import React from 'react';


function RootComponent () {

    return (

        <ParentComponent>

            <ChildComponent a="1" b="2" />

            <ChildComponent a="3" b="4" />

        </ParentComponent>

    );

}


function ChildComponent (props: ChildComponentProps) {

    return (

        <div>{JSON.stringify(props)}</div>

    );

}


function ParentComponent (props: ParentComponentProps) {


    /* 

    // Variant 1.

    return (

        <div>{

            React.Children.map(props.children, function (child: React.ReactElement<ChildComponentProps>): React.ReactElement<ChildComponentProps> {

                return React.cloneElement(

                    child, 

                    {

                        a: child.props.a + 1,

                        b: child.props.b + 2,

                        key: child.props.a + 1

                    },

                    null

                );

            })

        }</div>

    );

    */


    /*

    // Variant 2.

    return (

        <div>{

            React.Children.map(props.children, function (child: ChildComponent): ChildComponent {

                return (

                    <ChildComponent

                        {...child.props} 

                        {...{

                            a: child.props.a + 1,

                            b: child.props.b + 2,

                            key: child.props.a + 1

                        }} 

                     />

                );

            })

        }</div>

    );

    */


    // Variant 3.

    return (

        <div>{

            React.Children.map(props.children, function (child: React.ReactElement<ChildComponentProps>): React.ReactElement<ChildComponentProps> {

                return (

                    <child.type

                        {...child.props} 

                        {...{

                            a: child.props.a + 1,

                            b: child.props.b + 2,

                            key: child.props.a + 1

                        }} 

                     />

                );

            })

        }</div>

    );


}

React Modal Portal

Вариант с классом.


import React from 'react';

import ReactDOM from 'react-dom';


class Modal extends React.Component {


    modalDiv = undefined;


    constructor (props) {

        super(props);

        this.modalDiv = document.createElement('div');

    }


    render () {

        return ReactDOM.createPortal(

            this.props.children,

            this.modalDiv

        );

    }


    componentDidMount () {

        document.body.appendChild(this.modalDiv);

    }


    componentWillUnmount () {

        document.body.removeChild(this.modalDiv);

    }


}


class Parent extends React.Component {


    constructor (props) {

        super(props);

    }


    render () {

        return (

            <Modal>

                <Child />

            </Modal>

        );

    }


}


class Child extends React.Component {


    constructor (props) {

        super(props);

    }


    render () {

        return (

            <div className="modal-message">

                <h1>Hello</h1>

            </div>

        );

    }


}


Результат


<html>

    <body>

        <div id="app"></div>

        <div>

            <div class="modal-message">

                <h1>Hello</h1>

            </div>

        </div>

    </body>

</html>


Вариант с функцией.


import React, {useEffect, useState} from 'react';

import ReactDOM from 'react-dom';


interface PortalProps {

    children: React.ReactNode;

}


function Portal (props: PortalProps): JSX.Element {


    const [div] = useState(function (): HTMLDivElement {

        return document.createElement('div');

    });

    

    useEffect(function (): () => void {

    

        document.body.appendChild(div);

        

        return function (): void {

            document.body.removeChild(div);

        };

        

    }, [div]);

    

    return ReactDOM.createPortal(props.children, div);

    

}


interface ModalProps {}


function Modal (props: ModalProps): JSX.Element {

    return (

        <Portal>

            <div className="modal-message">

                <h1>Hello</h1>

            </div>

        </Portal>

    );

}


<html>

    <body>

        <div id="app"></div>

        <div>

            <div class="modal-message">

                <h1>Hello</h1>

            </div>

        </div>

    </body>

</html>