0

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 ?

2
  • you defined show const but using this.show. I would say that you need to replace this.show with show Commented Dec 19, 2019 at 13:23
  • 1
    That code does not make sense. You are iterating over two arrays, constantly reassigning one single variable. The resulting value is the result of the last iteration, that is, the last item in IdInstallGroup and installations. If you want to render one single value, find it first and then render it. If you want to render a list of items, you need to use map and return an array of elements. The iteration over IdInstallGroup should be probably removed and replaced with a single includes check. Commented Dec 19, 2019 at 13:44

2 Answers 2

1

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>;
  }
}
Sign up to request clarification or add additional context in comments.

Comments

0
 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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.