0

Here's a head-banging question! I've had this component of my app complete for a while. I decided to make a small, seemingly insignificant refactor that's causing something odd to break:

return (
  <div>
    {
      status === "Open" ? ( // REMOVED THIS
        <div style={{ color: "lightgrey" }}>
          <h1 className="text-center">
            {title} <span style={{ fontSize: "0.5em" }}>by {hostedBy}</span>
          </h1>

          <h3>
            {" "}
            <TournamentDescription key={_id} title={title} />{" "}
          </h3>
          <br />

          <p
            className="text-center"
            style={{ color: "#56A8CBFF", fontSize: "2em" }}
          >
            ~ {status} for registration ~
          </p>

          <h4 className="text-left mt-5">
            {participants.length === 1
              ? `${participants.length} Registered Fighter`
              : `${participants.length} Registered Fighters`}
          </h4>

          <ul>
            {participants &&
              participants.map((participant) => (
                <li
                  key={participant._id}
                  className="text-left"
                  style={{ fontSize: "1.1em" }}
                >
                  {participant.username}
                </li>
              ))}
          </ul>

          {isAuthenticated ? (
            <div>
              <TournamentSignUp
                participants={participants}
                userId={user._id}
                onClick={() => this.onSignUp(_id, user)}
              />
            </div>
          ) : (
            <Button block disabled>
              Log in to sign up for this tournament
            </Button>
          )}
          {isAuthenticated && user.username === hostedBy ? (
            <div>
              <StartTournament
                participants={participants}
                onClick={() => this.onStartTournament(_id, participants)}
              />
            </div>
          ) : null}
        </div>
      ) : (
        <TournamentStartPage /> // REMOVED THIS
      )
    }
    <br />
    <Link to="/">Back to Tournaments main page</Link>
  </div>
);

The idea was for what is shown to change once the Status is changed.

But when you click the link to get to this component, the UI flickers showing the "Closed" version first, and that's ugly. So I split em, the other component is now just in it's own file and this one is only going to render itself.

.. So I just removed that status==Open conditional.

So the same component from above now looks like

return (
  <div style={{ color: "lightgrey" }}>
    <h1 className="text-center">
      {title} <span style={{ fontSize: "0.5em" }}>by {hostedBy}</span>
    </h1>
    <h3>
      {" "}
      <TournamentDescription key={_id} title={title} />{" "}
    </h3>
    <br />
    <p className="text-center" style={{ color: "#56A8CBFF", fontSize: "2em" }}>
      ~ {status} for registration ~
    </p>

    <h4 className="text-left mt-5">
      {
        participants.length === 1 // THIS BREAKS
          ? `${participants.length} Registered Fighter` // THIS BREAKS
          : `${participants.length} Registered Fighters` // THIS BREAKS
      }
    </h4>

    <ul>
      {participants &&
        participants.map((participant) => (
          <li
            key={participant._id}
            className="text-left"
            style={{ fontSize: "1.1em" }}
          >
            {" "}
            {participant.username}
          </li>
        ))}
    </ul>

    {isAuthenticated ? (
      <div>
        <TournamentSignUp
          participants={participants}
          userId={user._id}
          onClick={() => this.onSignUp(_id, user)}
        />
      </div>
    ) : (
      <Button block disabled>
        Log in to sign up for this tournament
      </Button>
    )}
    {isAuthenticated && user.username === hostedBy ? (
      <div>
        <StartTournament
          participants={participants}
          onClick={() => this.onStartTournament(_id, participants)}
        />
      </div>
    ) : null}
    <br />
    <Link to="/">Back to Tournaments main page</Link>
  </div>
);

That breaks even though participants && participants.map() still works fine. Makes no sense to me.

The error I'm getting is Cannot read propery 'length' of undefined

To test it, I ran a console.log on participants and it shows two things in the console:

undefined
participants[]

That undefined thing is causing my component to break, but that apparently didn't exist before.
I cleared my data thinking it was something in there, but it's still happening (participants is an empty array right now, so it should be 0)

1 Answer 1

1

I don't see anything weird in what you're getting, perhaps status === "Open" was a guard clause to avoid undefined getting into that code, just add another guard clause where the error points at participants && participants.length === 1

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

5 Comments

Okay, I kept that conditional in and just put null. I dislike it though, because on the first render, the component flashes quickly between null (or the other component I had originally) first, and THEN renders the right one. It looks ugly. By just rendering the component without the conditional, it shows without flashing anything else. But again.. that issue. I'll keep trying things. Thanks though
@Cin88 when data is loaded from an async source you'll always have an undefined state unless you use SSR I think, usually you put a spinner or loading indicator while data is loading, I don't understand well your idea about avoiding the flickering
The flickering is basically.. when I put the conditional, its: "If status is Open, show FIRST, otherwise show SECOND" But what it always does is, even if the status is Open, it first shows SECOND really fast, and then shows FIRST. I wanted it to simply show THIS without that flicker. As for putting the spinner.. that's a great idea. But I really.. I have no idea how to do that. And what is SSR?
@Cin88 did you try my suggestion of let it as you had it and only add participants && before participants.length === 1? SSR stands for Server Side Rendering
EDIT It worked. I had to put participants && participants.length for all three sections of the ternary

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.