Quote Machine Project using React

guys give me your feedback :thinking:

Cool, it looks pretty good.

Iā€™d want it to start with a quote though. With a class, you can run a function once when it starts with componentDidMount.

Iā€™m not sure about:

    let oldIndex = 0;
    const newIndex = randNum(oldIndex, arr.length);
    oldIndex = newIndex;

Why are you setting the oldIndex to 0, then assigning it to the new index? First of all, the way randNum works, doesnā€™t it want the previous index, not 0? Youā€™d need to store the old index on state. Rather than store the quote and author on state, why not just store the index?

Also, your quote dataā€¦

Two things: First off all, Iā€™d want to get that our of the handleClick method just because of visual clutter and there is no need for it to be there. I would move it to the top of the file. I know we say we donā€™t like globals but this is kind of an exception - theyā€™re just constants. In a real world app, weā€™d probably import that from another file, or get it asynchronously, possibly with something like redux. But for now Iā€™d just move it out of the way.

The other thing is that I donā€™t like using two arrays for this. If this were a real world app, what if someone edited one but no the other? Accidents could happen. And if this were stored elsewhere in a file or gotten asynchronously, I would expect this to be one array, and array of objects, something like:

const quotes = [
  { author: 'Theodore Roosevelt ', quote: 'Believe you can and you're halfway there.' },
  { author: 'Zig Ziglar' , quote: 'You don't have to be great to start, but you have to 
start to be great.' },
  // ...
];

That is much closer to what I would expect the data to look like. Now the quotes are stored with the authors. Imagine if the business said they wanted you to come back and add dates, star ratings, places, sources, etcā€¦ Would you create new arrays for each of those? No, a ā€œquoteā€ is a ā€œthingā€ and should be stored as such.

But other than that, things look pretty slick. And by pointing these things out, Iā€™m not saying that you have to go back and change them or anything - Iā€™m just pointing them out

1 Like

i tried this but doesnā€™t seem to work canā€™t find the issue, also what tool can i use to debug jsx code ??

  const randNum = (currentIndex, size) => {
  const offset = Math.ceil(Math.random() * (size - 1));
  return (currentIndex + offset) % size;
};
   // the issue is in this method ...
 this.setState({
          index : randNum(this.state.oldindex, arr.length),
          quotes : quotes[this.state.index]
          });
 this.setState({
        oldindex : this.state.index
   });
 }

There are a couple problems here.

First of all, if this is still the same pen, these lines have a syntax error:

    {quote:"It had long since come to my attention that people of accomplishment rarely sat back and let things happen to them. They went out and happened to things.",
           "Someday is not a day of the week." ,author : "Leonardo da Vinci"},

Among other things, I would learn to format your code as you work - it makes it much easier to spot problems.

Iā€™m not sure what you are trying to do with your state:

    this.state = {
      index : 0,
      oldindex : 0,
      quotes : ''
    }

Why do you need to know the oldIndex. I think you needed that before, but donā€™t need it anymore. What is quotes? The name implies that it is more than one but you are setting state with only one.

So, where should your list of quotes go? I think the easiest place is just to make them a global variable in the pen, outside the class. True, global variables are ā€œiffyā€ but in reality, in a real app you would be either be importing them (which would make them a global variable inside the class) or you would be getting them asynchronously, which would have them on props or state, depending on where you handled it. You could also put them directly on the class as a class property, just:

  quotes = [
    {quote: "Believe you can and you're halfway there.",author : "Theodore Roosevelt"},
    // ...
   ]

inside the class. Then you could reference the array as this.quotes and any quote could be gotten with this.quotes[this.state.index].

Or if you really want it on state, you can add it to your state when you initialize it:

    this.state = {
      index : 0,
      quotes : [
        {quote: "Believe you can and you're halfway there.",author : "Theodore Roosevelt"},
        // ...
      ],
    }

Then the current quote can be accessed with this.state.quotes[this.state.index].

The next issue that I see is that your setting state.

First of all, if you have two _setState_s in a row, you donā€™t know how or when they are going to run - they are not synchronous. You should have done them in one:

 this.setState({
    index : randNum(this.state.oldindex, quotes.length),
    quotes : quotes[this.state.index]
    oldindex : this.state.index
  });

(Technically this should be a functional setState but letā€™s not worry about that right now.)

But as I said, I donā€™t think you need oldIndex and you donā€™t need to mess with quotes. All you need is:

 this.setState({ index: randNum(this.state.index, quotes.length),

Lastly, when you access the data in the JSX, e.g.:

  <h1 class= "text-center">"{this.state.quote}"</h1>

That wonā€™t work because that isnā€™t defined. Even quote is an object, not string (as written - I still think it should be an array.) I think that what you would want here is using the index off state to select off your quotes array and then you can dot notation into that to get your quote or author.


When I do those things, your code works for me. The choices I made were:

  1. Move the array quotes to the top of the file and make it a global constant.
  2. Fix the error in that array.
  3. Change the component state to be just index.
  4. Fix the setState to just set index.
  5. Fix how the JSX accesses the variables.

also what tool can i use to debug jsx code ??

Iā€™m not sure what you mean by debugging JSX - to me itā€™s all just JS and Iā€™m debugging.

The first level of debugging is to use a whole lot of console.log to see what is happening in the app. For example you could do a console.log(this.state); in your render method to keep track of what is happening.

The next level would be to use the other parts of your browser debugger, like inspecting elements, network traffic, etc. There are a lot of cool things you can do with this, like setting break points where your code will stop and you can observe your variables and step through your code.

Beyond that, there are extension you can add onto your browser to help debugging React and Redux - they are very cool. But I donā€™t know if they will work if you are still developing in Codepen.

For know, Iā€™d say that console.log and the browser console is your best friend. Note that codepen has a ā€œfakeā€ console built into it. You can also see the one in the browser debugger with ctrl-sft-J (or I) - or whatever. It sometimes has more info.

Donā€™t worry, youā€™ll pick this stuff up as you go.

1 Like

i followed the steps that you provided , and i have to admit that it is working better with this code, the UI became smooth
https://codepen.io/camper94/full/vYGBwRB

Cool. At a quick glance, it looks good.

Yeah, itā€™s hard in the beginning to know the right way to put things together. And React is very weird when you start - donā€™t get discouraged.

Just make sure you understand why we did the things we did and how they work, and now thatā€™s part of your coding vocabulary.

1 Like

The only thing Iā€™d add would be to make sure to learn to format your code as you go - it saves a lot of hassles in the long run.

1 Like