FabricioG
FabricioG

Reputation: 3310

How to place return code in a function: React

I currently have a react project I'm working on. My render method looks like this going into my return method:

   render() {
     let elements = [];
     this.dropdownCounter().forEach(item => {
       if(item != "attributeProduct") {
         console.log('setting');
         elements.push(
           <Dropdown
             title={this.state[item][0]['title']}
             arrayId={item}
             list={this.state[item]}
             resetThenSet={this.resetThenSet}
           />
         );
       }
    });
    this.state.attributeProduct.map(attributeItem => {
      elements.push(
        <Dropdown
          title={attributeItem.name}
          arrayId='attributeMetaProduct'
          list={
            this.state.attributeMetaProduct.filter(metaItem => metaItem.attribute_id == attributeItem.ID)
          }
          resetThenSet={this.resetThenSet}
        />
      );
    });
    return (

I have a lot of code going on in the render area due to different drop downs dependent on other methods. Is there a way that I can do something like this instead?

render() {
  allMyPrereturnStuff()
  return()
}

Then just place all this code in allMyPrereturnStuff()? I've tried creating this function and passing everything there but it doesn't work due to all the "this". Any ideas?

Upvotes: 0

Views: 4139

Answers (2)

Saša Tomislav Mataić
Saša Tomislav Mataić

Reputation: 1636

Don't forget to bind your allMyPrereturnStuff() method in the constructor so "this" will work inside it.

constructor(props) {
    super(props);
    // ... your existing code
    this.allMyPrereturnStuff = this.allMyPrereturnStuff.bind(this);
}

allMyPrereturnStuff = (params) => {
   // ... all the code
}

However, you might want to consider breaking out the code to components, which is more Reacty way to do things.

For example, you could refactor this

this.state.attributeProduct.map(attributeItem => {
      elements.push(<Dropdown
        title={attributeItem.name}
        arrayId='attributeMetaProduct'
        list={
          this.state.attributeMetaProduct.filter(metaItem => metaItem.attribute_id == attributeItem.ID)
        }
        resetThenSet={this.resetThenSet}
        />);
    });

To something like (somewhat pseudocody):

const DropdownList = (props) => {
    return (<Dropdown
            title={props.attributeItem.name}
            arrayId='attributeMetaProduct'
            list={props.list}
            resetThenSet={props.resetThenSet}
            />);
}

And in the original component's render function, have something like

render() {
    return (this.state.attributeProduct.map(attributeItem => {
      <DropdownList attributeItem={attributeItem}
        list={ this.state.attributeMetaProduct.filter(metaItem => metaItem.attribute_id == attributeItem.ID) }
        resetThenSet={this.resetThenSet}
        />);
}

Upvotes: 1

Matthew Herbst
Matthew Herbst

Reputation: 31963

Yes, you can easily drop in normal javascript expressions into JSX:

return (
  <div>
    {this.renderStuff()}
    {this.renderOtherStuff()}
    {this.renderMoreStuff()}
  </div>
);

You can even base it on flags:

const shouldRenderMoreStuff = this.shouldRenderMoreStuff();

return (
  <div>
    {this.renderStuff()}
    {this.renderOtherStuff()}
    {shouldRenderMoreStuff ? this.renderMoreStuff() : null}
  </div>
);

Do note that it is often an anti-pattern to have render* methods in your components other than the normal render method. Instead, each render* method should probably be its own component.

Upvotes: 3

Related Questions