1

I'm trying to render some loading elements (just empty <li>'s at this point) within a component while I wait for axios to retrieve data from my backend. To do this I'm using a ternary operator, but for some reason I'm not getting any rendering from it - no matter if the condition is evaluates to true or false.

My Code

class Content extends React.Component{
    constructor(){
        super();
        this.state = { currentItemIndex: 0 };
    }

    render(){
        // results will either be an empty array [] or an array populated with objects
        let results = this.props.results;
        return <div className="content">
            // note that this className will return the correct results using the same logic
            <div className={(results.length ? "results" : "loading")}>
                <ul>{ 
                    results.length ? 
                    // results has data so render it all out
                    results.map(data => {
                        const index = this.state.currentItemIndex + 1;
                        this.setState({ currentItemIndex: index });

                        return <Result key={data.slug} data={data} index={index} />
                    }) :
                    // results has no data so render 8 empty list elements
                    new Array(8).map(() => <li></li>)
                }</ul>
            </div>
        </div>;
    }
}

So, using the above code, whether my results array is populated or not, it will neither render the <Result /> component OR the 8 empty <li>'s like it should. Even stranger, if I change the code to something like this:

{ results.length ? "there are results" : "no results" }

It will do it just fine.

I'm fairly new to React so the problem may seem obvious, but as far as I'm aware, I'm doing everything correctly. All help is appreciated, cheers.

4
  • Try to inspect the elements with DevTool, my guess is its a CSS problem. For further help try making reproducible example in a sandbox. codesandbox, How to create a Minimal, Reproducible Example Commented Jul 12, 2020 at 18:16
  • @DennisVash Not a CSS problem, the elements don't ever appear in the DOM. Commented Jul 12, 2020 at 18:16
  • Also, you mutate state ++this.state.currentItemIndex, stackoverflow.com/questions/37755997/… Commented Jul 12, 2020 at 18:18
  • @DennisVash oh, thanks for that pickup, didn't even notice. Commented Jul 12, 2020 at 18:18

1 Answer 1

1

A couple of things:

  1. You are calling this.setState() in the render which will result in a Maximum update depth exceeded error. I'm not sure what you are doing with the currentItemIndex, but you should move that this.setState() call to some handler outside of the render.

  2. You don't get an array with 8 elements when you do new Array(8). From the docs on Array() constructor:

If the only argument passed to the Array constructor is an integer between 0 and 232-1 (inclusive), this returns a new JavaScript array with its length property set to that number (Note: this implies an array of arrayLength empty slots, not slots with actual undefined values)

In your case, there are no items in the array so the map returns no list items.

You can achieve this by doing:

Array.from({ length: 8 }).map((x) => {
  console.log(x);
  //you could return <li></li> in your case
});

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, this helped a lot. I ended up just using the useState hook to update my index and converted my class component to a functional component.

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.