33

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?

bukowski
  • 1,893
  • 7
  • 34
  • 54
  • you cannot change state or prop during render, you can use componentDidUpdate or componentWillReceiveProps for it – abhirathore2006 Oct 22 '16 at 14:03
  • Cloning component here is a bad option because it will affect the performance by creating extra memory for the cloned components. And, after cloning the original components become usless. Again, this is a bad way of implementing. – Pranesh Ravi Oct 23 '16 at 02:59

4 Answers4

58

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>
Chara Plessa
  • 691
  • 5
  • 6
6

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/

Maciej Sikora
  • 19,374
  • 4
  • 49
  • 50
  • When `C` becomes `null`, as I see no `default` case in the `switch` to handle this case, React will throw an error. You can try it! – Pranesh Ravi Oct 22 '16 at 15:04
  • @PraneshRavi very funny, and where You see default for false? And what have react to standard switch statement? Yes try it yourself! Question was about how set props to dynamic assigned component, not about default in switch. – Maciej Sikora Oct 22 '16 at 16:04
  • Check code with false with id 3 and the same problem occurse, my change on null are not doing any harm. You comment not have sense You give me -1 because orginal answer had no default in switch. And I have proper reason for downvoting You answer - downvoting my answer without any reason is first, next is that You answer is poor answer. – Maciej Sikora Oct 22 '16 at 16:19
  • Check my snippet. Try to make your code work. When you pass `id="3"`, your code will break – Pranesh Ravi Oct 22 '16 at 16:19
  • I repeat again, switch without defaut was in orginal code, it is not part of my answer. Please read my comments, you are arguing about switch statement not about real answer content. I added default to stop this conversation without sens, but it has no meaning for it. And Dude You are very irritating guy. Realy You started this conversation without any reason! – Maciej Sikora Oct 22 '16 at 16:22
  • I completely agree, you answer is based on **dynamic tag name** for react component. I get that. In this case, if you don't add an `default` in your switch, if `id=3`, `C` will be `null`. So, React will throw an error. Did you get it? – Pranesh Ravi Oct 22 '16 at 16:25
  • If you're so sure, remove the `default` and try passing `id` as 3. Add a working example. – Pranesh Ravi Oct 22 '16 at 16:26
  • With false also would be an error, I checked it. Good luck! – Maciej Sikora Oct 22 '16 at 16:27
  • https://jsfiddle.net/Lnqzoa4j/ This is your fiddle without `default`. It's not even loading. Open the console and see. – Pranesh Ravi Oct 22 '16 at 16:29
1

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>
Ester Kaufman
  • 708
  • 10
  • 20
0

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.

Pranesh Ravi
  • 18,642
  • 9
  • 46
  • 70
  • 2
    Switch by id has no connection with items loop so should be called outside, You are doing the same operation in every loop and this operation should be done only one time. This code gives poor performance and it is bad practice. – Maciej Sikora Oct 22 '16 at 16:07
  • @MaciejSikora Added a working example. Hope this clarifies! – Pranesh Ravi Oct 22 '16 at 16:18