Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

react - can you mutate modify this.props.children to dynamically (programatically) add children components

According to fb docs, this.props.children is an opaque data structure and should not be manipulated directly.

In fact, the docs say that we should use the library functions in React.Children

Looking at the library functions, they are all getters, which leads me to believe that we should not be mutating this.props.children

Is this true? Can we mutate this.props.children (such as inserting a component dynamically, etc)?

Thanks!

like image 995
dev Avatar asked Sep 19 '25 02:09

dev


1 Answers

You can't (or shouldn't) mutate the children directly. You can however "modify" its output via mapping:

const Hydrogen = props => (<div>{props.weight}</div>);
const Oxygen = props => (<div>{props.weight}</div>);

const Water = props => (
    <div className='water'>
    {React.Children.map(props.children, child => (
        React.cloneElement(child, {
            weight: props.weight / React.Children.count(props.children)
        })
    ))}
    </div>
);

const WaterBalloon = props => (
    <div className='water-balloon'>
        <Water weight={3}>
            <Hydrogen />
            <Hydrogen />
            <Oxygen />
        </Water>
    </div>
);

Here I "modify" the children passed to Water, passing the weight property to them.

If you need the ability to "add/remove", perhaps you should consider redesigning in such a way that you maintain an array of "data" and then populate components from that data:

https://jsfiddle.net/814jze3z/

const Item = props => (
    <li>{props.time}</li>
);

class List extends React.Component
{
    constructor() {
        super();
        this.state = {
            items: []
        };

        this.addItem = this.addItem.bind(this);
        this.removeItem = this.removeItem.bind(this);
    }

    addItem() {
        let item = {
            id: this.state.items.length + 1,
            time: +new Date()
        };

        this.setState({
            items: this.state.items.concat([item])
        });
    }

    removeItem() {
        this.setState({
            items: this.state.items.concat().splice(1)
        });
    }

    render() {
        return (
            <div>
                <button onClick={this.addItem}>Add Item</button>
                <button onClick={this.removeItem}>Remove Item</button>
                <ul className='list'>
                {this.state.items.map(item => (
                    <Item key={item.id} time={item.time} />
                ))}
                </ul>
            </div>
        );
    }
}
like image 111
noahnu Avatar answered Sep 20 '25 17:09

noahnu