Question about Redux Store vs. Global Variables [SPOILERS FOR RANDOM QUOTE MACHINE]

I am writing my first React/Redux project, and I have a question about the Store. Without looking at the code of the example project, I am assuming that the quotes are stored locally, not fetched through some API (as we haven’t done back-end yet). Which, to me, means that the dataset is going to be an array of objects:

[
{quote: 'Aaa', author: 'Bbb'},
{quote: 'Ccc', author: 'Ddd'},
{quote: 'Eee', author: 'Fff'}, ...
]

So, the crux of my question is: do the principles of Redux (application state in one place) mandate that:

  1. I keep the entire array in the store.state
  2. Keeping track of indexOfQuote in state is enough?
  3. Or, because this is React/Redux, should:
    state = { currentQuote: 'Xxx', currentAuthor: 'Yyy' };

(1) keeps everything in the store, (2) is the most abstract representation of state, and (3) is what I think (perhaps erroneously) React/Redux demands for props to work.

I would say this is a strange one to use Redux for because I can’t imagine more than one component is needed for this. It really is just a box with a quote. What other components need access to the quote?

Why don’t you try making one of the full stack apps?

1 Like

I’ve read that one. It’s mostly for practice to force myself to do what I find harder: merging Redux and React.

1 Like

For practice connecting the two in a simpler environment with fewer moving parts.

I get that but I would argue, if you are ready to learn React and Redux you are ready to do a full stack app.

I highly doubt the first multiplication problem you were given was the product of 243,567 x 42. That is the best analogy I can make for what you are proposing. A language is learned by syntax and vocab lessons. Your replies are not answering my initial question, which is about the philosophy of Redux: Do global variables outside of the store + an abstracted representation of state have a place?

To be honest, I don’t know. I’ve done one project with Redux and I found it confusing. I have a udemy course to go through yet which will hopefully clarify. The beta freecodecamp lessons haven’t helped.
You never mentioned what components you have in your app.
I suggest you build it and see what happens.

Just to clarify something about this project, you can use an API without learning anything about the back-end at this point. In fact, you have already learned to use what I will call a “quasi” API to request data (JSON file) from a different source using jQuery in the following challenge.

https://www.freecodecamp.org/challenges/get-json-with-the-jquery-getjson-method

There is a big difference in using an API (which can be done on the front-end client) and building an API (done on the back-end).

1 Like

Fair enough. But I know of know API endpoint that delivers quotes :). Any thoughts on my initial question about whether a global variable in parallel to an abstracted representation of state inside the store is within the philosophy of redux?

Sorry, I have not yet used Redux. Someone else who has is sure to reply though.

1 Like

A real world example would be a header component which handles sign in / sign out and authentication and other components which change when the user is authorized or not.
Redux is for sharing state among all components in an app.
I still don’t see how your quote machine has more than one component.

I think I just thought up the answer: If the goal of the reducer is to be a pure function, with no outside dependencies, then in mathematical terms, it is a pure function of the parameters:

(Input domain)==(mapping onto)==>{Output range}
(currentState, action) ==(mapping onto)==>{newState}.

Thus, if I’m going to define an array of quotes, by purist standards, it should be in the reducer. As for concerns about memory and processing costs, I guess that is subordinate to the “one store of truth” philosophy.

Ah, i’m still drowning in the recipe app project trying to use react-redux to learn it ^^
And that is exactly one of the problem i’m still facing: thinking about the FCC beta go-through they hold all the messages in the store, not just the index …now i’m thinking about to use json object in there not just one-dimensional array, but the concept is the same and i’m following this path ( even if at the moment is a ‘pain in the ass’).

I know you’ve kinda gone on exploring from the first post, but 1 is how it should be done. The array of quotes is the state, and React is designed so as to map that state to visual representation. You probably also want 3, so you have an object with the array of quotes as one property, the current quote as another and so on. That is also part of the state. Redux is a way to keep all of the state insulated from the functional part of the app.

The issue with functional approaches is that every function should ideally be pure, so if you give it some thing it will always return the same result as long as that thing is the same. Which means, basically, state is difficult to deal with, because it often involves side effects, which are verboten. So there are different approaches, but they boil down to:

You move the state somewhere else, behind a safe interface, and you only interact with it via that interface[1]. In the case of Redux, you put all[2] the state in one object, the store, and you interact with it via reducers. The reducers are just functions, they don’t have any state whatsoever. You could [almost] uninstall Redux, just leaving those reducers, replace the store entirely with a data structure of the same shape, and if you hand the reducer function that data they will still work (obviously there are a few helper functions that Redux provides that mean you’re unlikely to be able to do this in practice, but this is basically true).

The other major benefit of holding all the state in Redux is that Redux mandates that the data is immutable. This means in practice that you can go back and forth in history within the app because it becomes trivial to keep a record of every change that ever happened to the state.


[1] For example, in Haskell you use a construct called a monad, one that is designed to handle state - if you have used Promises in JS, those are essentially a type of monad, they work the same way. With monads for state, you wrap your data in a monad, which does the work, then you unwrap it to get a value - like with a promise, a fetch request gets wrapped in a promise, and the value gets got (or not), then you unwrap the promise to get the value out.
[2] In practice, you don’t put all the state in the store, because this is a bit ridiculous - a good example is listening to characters typed into a search box. You could update the store with the new value every time a user hits the keyboard, but in practice what you do is have a component with state, and you update the state of that component only. Then when, say, the user hits enter, then you save the full value they are searching for to the store.

2 Likes

Thanks, Dan. As I was writing up my reducer, I realized that, in practical terms of actually implementing this, I could go down the path of:

  • (2) setting the state parameter to a default integer from [1, array.length as an integer literal].
  • (3) setting the default parameter to a quote object randomly chosen from the array (no integer literals needed).

I know this goes against what you said in the beginning of your detailed and well thought-out reply (which I read twice), but I believe it agrees with your latter argument that “the quote is the state,” and that’s what should be in the store. I realized that this version required the array to be declared as a global constant, which structurally is equivalent to getting the quotes from some API, and could even be written as a function getRandomQuote() that stands in for the API call, which also helps me meet the project criteria of having a random quote on load. Does my thinking (now more specific) seem to fly?

1 Like

In my react redux roguelike project I set my weapon types in a constant array that I would just access with import * as itemTypes from './../constants/itemTypes'; with itemTypes.WEAPONS like in playerActions where I say let weapons = itemTypes.WEAPONS;.

I imagine my quote array would be a constant also, like you mention, but making it a global is probably not a good idea.

So the current active quote would be in the state. New quotes would be obtained through actions where they will be randomly picked from a constant array and then placed into the state through a reducer.

1 Like

Thanks. I think this is probably the best practice to build scalable modular apps (export a function like getRandomQuote() from another file that I can then call from inside an action creator). I totally wasn’t thinking about exports—the ES6 section of FCC was kind of a blur, but it’s the one to which I’ve been going back to constantly in order to answer questions I’m about to ask in the forum.

Thanks @DanCouper && @DuskyPixel. I really appreciate the focused discussion on Redux principles, and the perspective and experience you shared have completely answered my question. My only regret is that I can only give one “solution” mark. The truth is you both deserve it.