21

I have a code in react that looks something like this:

class UserManagement extends React.Component {
    constructor() {
        super();
        this.state = {
            users: undefined,
        };
    }

    componentWillMount() {
        // load the users state with a Promise
        setTimeout(() => {
          this.setState({users: []});
        }, 800);
    }

    render() {
        if ( this.state.users === undefined ) {
            // until the users state is updated, I want to return an empty element
            return null;
        }

        // real site rendering
        return <div>We have users</div>;
    }
}

ReactDOM.render(
  <UserManagement />,
  document.getElementById("root")
);
<div>Will be blank at first while we don't have users, then show "We have users" after 800ms when we have users</div>
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

My question is: How to return an empty element until the users state is returned? I tried to return (null) as suggested in some places, but the browser raise this error:

Uncaught TypeError: Cannot read property 'style' of null

I am aware of the option to return (<div></div>), but I am not sure that this is the best practice in this case.

Thnaks!

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
Yuval Pruss
  • 8,716
  • 15
  • 42
  • 67
  • @Rajesh throws the same error as `(null)` – Yuval Pruss Jul 26 '17 at 09:07
  • 1
    The React docs [say you should be able to return `null`](https://facebook.github.io/react/docs/conditional-rendering.html#preventing-component-from-rendering), so it's strange this isn't working. – Joe Clay Jul 26 '17 at 09:08
  • 2
    Returning `null` works just fine. Please update your question with a **runnable** [mcve] using Stack Snippets (the `[<>]` toolbar button) demonstrating the problem with doing that. Stack Snippets support React, including JSX; [here's how to do one](http://meta.stackoverflow.com/questions/338537/). – T.J. Crowder Jul 26 '17 at 09:08
  • My apologies. Rushed to comment. Are you manipulating the style of this component anywhere else – Rajesh Jul 26 '17 at 09:09
  • Actually, I've added the snippet for you. Works a treat. Please update it to demonstrate the problem you're having. – T.J. Crowder Jul 26 '17 at 09:09
  • @T.J.Crowder My bet is OP is manipulating the style property of this component somewhere in the code. All OP needs is to add a check before doing it – Rajesh Jul 26 '17 at 09:11
  • 1
    @Rajesh: It'll be something along those lines, yeah. :-) Until they update, we can't answer the question properly. – T.J. Crowder Jul 26 '17 at 09:11
  • I have an error in my code and now it's working.... this code works just fine, it's my fault... – Yuval Pruss Jul 26 '17 at 09:14

7 Answers7

30

Just in case anyone want another approach:

Since React v16.2 you can use Fragments allowing to add an empty JSX tag like this:

  return (
    <>
      <ChildA />
      <ChildB />
      <ChildC />
    </>
  );

Example extracted from official docs.

So in your case, returning a Fragment without any childs, works.

  return <></>;
dnarvaez27
  • 472
  • 1
  • 6
  • 10
11

I think just add { null } not null, in your section to show empty component.

Have you tried it already ?

manggaraaaa
  • 802
  • 1
  • 8
  • 23
7

Ok so as Facebook says :

Since React's release, people have been using work arounds to "render nothing". Usually this means returning an empty or . Some people even got clever and started returning to avoid extraneous DOM nodes. We finally provided a "blessed" solution that allows developers to write meaningful code. Returning null is an explicit indication to React that you do not want anything rendered. Behind the scenes we make this work with a element, though in the future we hope to not put anything in the document. In the mean time, elements do not affect layout in any way, so you can feel safe using null today!

FrenchTechLead
  • 1,118
  • 3
  • 13
  • 20
7

You need to wrap it in a React.Fragment tag.

<React.Fragment></React.Fragment>
donatJ
  • 3,105
  • 3
  • 32
  • 51
Taghrid Kam
  • 91
  • 1
  • 1
  • 1
    Please consider adding some form of explanation or more detail to your answer. Code only answers are typically discouraged. – Axe319 Oct 06 '20 at 17:36
1

use the react Fragment <></>. One of its advantages is that it does not create additional Dom nodes into rendered component (such as an empty div tag).

You can use ternary condition to make your code more readable.

    render() {
        ( this.state.users === undefined ) ?
            return <></>   
        : return <div>We have users</div>;
    }

or oven simpler syntax would be

    render() {
        ( this.state.users) ?
            return <div>We have users</div>  
        : return <></>;
    }
Nada Touil
  • 317
  • 3
  • 12
  • This won't work. `return` is a [statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return), whereas the ternary operator wants an [expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators). You should `return` the whole `ternary` expression and remove the `return`s from the inside – Zachiah Nov 10 '22 at 15:35
  • you should try it . Please check conditionnal rendering in react official page https://reactjs.org/docs/conditional-rendering.html. Just instead of "if else" , I used ternary condition – Nada Touil Nov 15 '22 at 14:10
  • The difference is that `if` and `else` take statements whereas the ternary takes an expression – Zachiah Nov 16 '22 at 16:05
0

I think you should add ternary operators like:

this.state.users? return null : return <div>We have user<\div>
0

One thing I did using React.useState was to initialize an empty JSX.Element object like so

const [jsxObject, setJsxObject] = React.useState(<></>);

Then, in whatever function you want to return a JSX.Element

setJsxObject(<h1>whatever inside</h1>);

Render it in the component

{jsxObject}
beeeliu
  • 99
  • 1
  • 1
  • 6