Cover image for How to Make a Weird Psychedelic Eye Cloud Using React

How to Make a Weird Psychedelic Eye Cloud Using React

julianeon profile image Julian Martinez ・5 min read

Ok, this is kind of a joke on boring React tutorials: you're bored of reading them, I'm bored of writing them.

Here's something a little out of the ordinary, for variety's sake.


The basic concept is to use react-bootstrap, a UI library, to start with a simple unit - you can think of it as an eye emoji - and keep 'stepping' it up, line by line, until you have a half-screen full of increasing numbers of emoji on each line.

Then you do the same thing in the reverse direction, ending at 0.

Then, because the best part of this is being able to change it and see the changes in action, there's a button that changes the total number of lines, so you can see the number of emoji (with colors) shrink or expand, according to your preference.


It's then pushed from GitHub to AWS, as a static site, on S3 - as you can see above.

Concepts Involved

There's a lot going on here, but I'll do my best to break it into its constituent steps. Also, practically every unit here corresponds to something you can see, and that makes it easier.

There's useState, which holds the total number of rows, so the button can change it (otherwise, it could just be a constant - no state, or useState, needed).

The way the app works is something like this.

We start with this, after earlier setting total=40:

const upOrder=[...Array(total/2).keys()]

This yields a value of 20, and creates an array that looks like this:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

This get used in a component which goes through that array, number by number. Each number represents a 'row' of eyes.

The program moves through the array, starting from 0: 0, 1, 2, 3, 4, 5... Let's pause it at 5, to show what it's doing.

At 5, there's a component that creates a new array, that goes from 0 to 5: [0,1,2,3,4,5].

Then the app draws, on the screen, a row with that many elements, dropping an eye emoji in each one, and coloring it according to a selection from the range of allowable colors you gave it.

Then we return to the component I mentioned at the top, which moves on to the next number, 6, and repeats the process - creating a new row with one element each for [0,1,2,3,4,5,6] with an eye emoji and a color.

And so on all the way up to the top number - here, 19. At this point, there's 19 rows with emoji eyes, with 1 emoji eye in the first row and 19 emoji eyes in the last row (because the 0 row has 0 eyes).

Then the program starts up again from the top, this time using a different array:

[19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

And that gets you your screen of eye weirdness, shown in the screenshot.


This app, in terms of written code, is basically just one file, App.js.

Each component may be short, but each component does a lot of work, so it really makes sense to take it section by section.

function App() {
    const [total,setTotal]=useState(40);
    const lowerBound=4;
    const upperBound=100;
    const clr=["red"];
    const upcolors=["red","blue"]
    const downcolors=["teal","pink","green","silver","brown","purple","gold"]
    return (
    <div style={{backgroundColor:'red',height:'100vh'}}>
          <div style={{position: 'sticky', top: '0',zIndex:'1'}}>
            <Button variant="light" onClick={()=>{if (total<=upperBound) { setTotal(total+2) }}}>Increase</Button>
            <Button variant="dark" onClick={()=>{ if (total>=lowerBound) { setTotal(total-2) }}}>Decrease</Button>

          <LayerWall lines={[...Array(total/2).keys()]} colorRange={upcolors}/>
          <LayerWall lines={[...Array(total/2).keys()].reverse()} colorRange={downcolors}/>

export default App;

In the App component, there are buttons, which can change the number of rows. That's why you have to have 'state' - so that the screen can be redrawn as a result of updates to it.

I have an 'upperBound' and a 'lowerBound' there - upperBound so the screen doesn't become a garbled mess of too many eye emoji, and a lowerBound so there can't be fewer than that many rows on the screen. (Also, if it goes below 0, the program will crash, since it doesn't know what to do with an array of size smaller than 0).

It's simple. When you press the button to increase, it increases the number of rows by 2. When the you press the button to decrease, it decreases it by the same amount, also 2.

The reason it's 2, and not 1, is because the number of rows has to be divisible by 2; we have to divide the number in half to do the upward-ascending and downward-ascending clouds of eyes.

I also set the colors to the ones in the range you see above, for the up-section and the down-section; feel free to change those.


There's a few components at work here: LayerWall, Layer, and Unit.

LayerWall is half of it: one LayerWall builds the upper half, one LayerWall builds the lower half. I did it in two pieces so they could be separately colored, as they are in the screenshot.

Layer is basically the Row of Eyes.

Unit is each eye: the small colored container it is in, and the height. This varies based on the number of rows in all, so that basically no matter how many or how few, it fills the size of one screen, designated as 100vh in css. The vh stands for vertical height, and by convention, 100vh equals the size of whatever screen you are viewing it on (the css processor handles that math).

And that's it! You can see the app in action here:


The GitHub repo is here:


You can also read this tutorial, and other tutorials like it, on my website:


My name is Julian Martinez and I'm a consultant for web and cryptocurrency projects. If you'd like to discuss a project, see my About section & contact form.

For more content like this, follow me on Twitter.

Posted on by:

julianeon profile

Julian Martinez


I'm interested in development as it relates to JavaScript, React, AWS, Go, and cryptocurrencies. Also I'm friendly.


markdown guide