bukowski
bukowski

Reputation: 1943

Set component's props dynamically

I need to set component's props after it is stored in a variable, here is pseudo code:

render(){

    let items = [{title:'hello'}, {title:'world'}];
    let component = false;

    switch (id) {
      case 1:
        component = <A />
        break;
      case 2:
        component = <B />
        break;      
    }

    return(
      items.map((item, index)=>{
        return(
          <span>
            {/* SOMETHING LIKE THIS WOULD BE COOL - IS THAT EVEN POSSIBLE*/}
            {component.props.set('title', item.title)}
          </span>11

        )
      })
    )
  }

Inside return I run a loop where I need to set props for the component that is stored inside a variable.... How to set props for this component which I stored earlier in a variable?

Upvotes: 35

Views: 44378

Answers (4)

Ester Kaufman
Ester Kaufman

Reputation: 868

More Use-cases Example -> for other people that came here:

A way of dynamically rendering all items from pre-declared array with all components and their props:

const items = [{component: Home,props:{ icon: 'fa-home', title: 'Home Page'}},{...}]

<div>
    {
       items.map((item) => {
          let Child = item.component;
          return (<Child {...item.props}/>);
       });
     }
</div>

Upvotes: 2

Chara Plessa
Chara Plessa

Reputation: 699

The proper way is to use React's cloneElement method (https://facebook.github.io/react/docs/react-api.html#cloneelement). You can achieve what you want by doing:

<span>
  {
    React.cloneElement(
      component,
      {title: item.title}
    )
  }
</span>

Upvotes: 58

Pranesh Ravi
Pranesh Ravi

Reputation: 19113

You can move the switch inside the map(). Hope this helps!

class A extends React.Component{
  render(){
    return <h1>Inside Component A:{this.props.title}</h1>
  }
}

class B extends React.Component{
  render(){
    return <h1>Inside Component B: {this.props.title}</h1>
  }
}

class Parent extends React.Component{
  render(){
      let items = [{title:'hello'}, {title:'world'}];
      const finalItems = items.map((item, index) => {
         switch (parseInt(this.props.id)) {
            case 1:
             return <A title={item.title}/>
            case 2:
             return <B title={item.title}/>     
         }
       })

      return(
        <span> {finalItems} </span>
      )
    }
 }
ReactDOM.render(<div>
                  <Parent id="1"/>
                  <Parent id="2"/>
                  <Parent id="3"/>
                </div>,
  document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

You don't need to add a default case as React will ignore undefined, which will be returned to the map when the switch case fails.

Upvotes: 0

Maciej Sikora
Maciej Sikora

Reputation: 20132

It can be done by assign not jsx but component reference, then use jsx in looping with using of component from variable. Check my code changes.

render(){

let items = [{title:'hello'}, {title:'world'}];
let C = null; //null is more accurate for object variable

switch (id) {
  case 1:
    C = A; //it is component reference, C must be from upper letter
    break;
  case 2:
    C = B; //it is component reference
    break;
  default:
    C = A; //good to have default for wrong ids      
}

return(
  items.map((item, index)=>{
    return(
      <span>
        <C {...item} /> //render component with props
      </span>11

    )
  })
)
}

Most important things:

1.C=A; we set on variable C reference to target component

2.<C {...item} /> all properties from item object will be set in child component.

3.It can be used in standard way like: <C title={item.title} />

Some working example: https://jsfiddle.net/maciejsikora/jtt91wL3/3/

Upvotes: 6

Related Questions