Gabriel Silva
Gabriel Silva

Reputation: 109

problems with conditional render REACT

I'm trying do a conditional render in react, but isn't work.

That is my function:

populateBodyInstallationsEdition() {
    letshow = null;
    console.log(this.state.installations);
    for (let i = 0; i < this.state.IdInstallGroup.length; i++) {
      for (let j = 0; j < this.state.installations.length; j++) {
        console.log(this.state.IdInstallGroup[i]);
        console.log(this.state.installations[j].id);
        if (this.state.IdInstallGroup[i] === this.state.installations[j].id) {
          show = (
            <div>
              <div>
                <input
                  type="checkbox"
                  value="None"
                  className="test"
                  id={this.state.installations[j].id}
                  name={this.state.installations[j].Name}
                  checked
                />
                {/* <label htmlFor={arr[index].id} /> */}
              </div>
              <label htmlFor={this.state.installations[j].id}>
                {this.state.installations[j].Name}
              </label>
            </div>
          );
        } else {
          show = (
            <div>
              <div>
                <input
                  type="checkbox"
                  value="None"
                  className="test"
                  id={this.state.installations[j].id}
                  name={this.state.installations[j].Name}
                />
                {/* <label htmlFor={arr[index].id} /> */}
              </div>
              <label htmlFor={this.state.installations[j].id}>
                {this.state.installations[j].Name}
              </label>
            </div>
          );
        }
      }
    }
    return show;
  }

the conditions are making the right comparisons but don't rende the JSX

what could be wrong ?

how can i solve this problem ?

Upvotes: 0

Views: 88

Answers (2)

Rolo
Rolo

Reputation: 3413

Ok, right to the answer...

If you want to render ALL installations:

  1. Replace let show = null; with let show = [];
  2. Replace show = ( with show.push(

That's it... Why? Because your function is iterating both arrays and always setting 'show' to the current component depending on the condition, this will always render only one component.

Updating the code as suggested above will add each one of the "conditional" components to an array that will be then rendered, not only one.

However, I can't say that it is the right solution just because it will work, let me show you other alternatives to implement this in a better way.

Option 1: Following the same approach, but without duplicating code.

Both components of the condition are exactly the same, except for the "checked" attribute, react allows you to do this:

populateBodyInstallationsEdition = () => {
    let show = [];
    for (let i = 0; i < this.state.IdInstallGroup.length; i++) {
      for (let j = 0; j < this.state.installations.length; j++) {
        show.push(
          <div>
            <div>
              <input
                type="checkbox"
                value="None"
                className="test"
                id={this.state.installations[j].id}
                name={this.state.installations[j].Name}
                checked={this.state.IdInstallGroup[i] === this.state.installations[j].id} // <=PAY ATTENTION HERE
              />
            </div>
            <label htmlFor={this.state.installations[j].id}>
              {this.state.installations[j].Name}
            </label>
          </div>
        );
      }
    }
    return show;
  };

Relevant code checked={this.state.IdInstallGroup[i] === this.state.installations[j].id}

Option 2: Extract a component

//This component can go on a separate file
const MyComponent = ({id, name, isChecked = false}) => {
  return(
    <div>
      <div>
        <input
          type="checkbox"
          value="None"
          className="test"
          id={id}
          name={name}
          checked={isChecked}
        />
      </div>
      <label htmlFor={id}>
        {name}
      </label>
    </div>
  )
}

populateBodyInstallationsEdition = () => {
    let show = [];

    for (let i = 0; i < this.state.IdInstallGroup.length; i++) {
      for (let j = 0; j < this.state.installations.length; j++) {

        let id = this.state.installations[j].id;
        let name = this.state.installations[j].Name;
        let isChecked = this.state.IdInstallGroup[i] === this.state.installations[j].id;

        show.push(
          <MyComponent id={id} name={name} isChecked={isChecked} />
        );
      }
    }
    return show;
  };

Option 3: Get rid of the 'populateBodyInstallationsEdition' function and use 'map' in the render body (Using the same component we defined before)

const installations = [
  {
    id: "group1",
    Name: "Some name"
  },
  {id:..., Name:...}
  ...
]

class App extends React.Component {
  state = {
    IdInstallGroup: ["group1", "group2", "group3", "group4"],
    installations: installations
  };

  render() {
    return <div className="App">
      {
        this.state.IdInstallGroup.map(group => 
          this.state.installations.map(installation => 
            <MyComponent id={installation.id} name={installation.Name} isChecked={group === installation.id} />
          )
        )
      }
    </div>;
  }
}

Upvotes: 1

Krina Soni
Krina Soni

Reputation: 930

 import React from 'react';

const populateBodyInstallationsEdition = () => {
    return (
        <React.Fragment>
            {
                IdInstallGroup && IdInstallGroup.map((group) => {
                    return (
                        installations && installations.map((install) => {
                            return (
                                <div>
                                    {
                                        this.state.IdInstallGroup[group] === this.state.installations[install].id ?
                                            <div>
                                                <div>
                                                    <input
                                                        type="checkbox"
                                                        value="None"
                                                        className="test"
                                                        id={this.state.installations[install].id}
                                                        name={this.state.installations[install].Name}
                                                        checked
                                                    />
                                                    {/* <label htmlFor={arr[index].id} /> */}
                                                </div>
                                                <label htmlFor={this.state.installations[install].id}>
                                                    {this.state.installations[install].Name}
                                                </label>
                                            </div>
                                            :
                                            <div>
                                                <div>
                                                    <input
                                                        type="checkbox"
                                                        value="None"
                                                        className="test"
                                                        id={this.state.installations[install].id}
                                                        name={this.state.installations[install].Name}
                                                    />
                                                    {/* <label htmlFor={arr[index].id} /> */}
                                                </div>
                                                <label htmlFor={this.state.installations[install].id}>
                                                    {this.state.installations[install].Name}
                                                </label>
                                            </div>
                                    }
                                </div>
                            )

                        })
                    )

                })
            }
        </React.Fragment>
    )
}

export default populateBodyInstallationsEdition;

Try this way of conditional rendering. Also, You may use map to loop through the each element and put conditions inside it.

Upvotes: 0

Related Questions