I am new to react and I'd like to ask a high-level question. Any directional advice will be welcome.
So, here is what I did in vanilla JS. I defined an empty variable first, and put the results of a DB query there. Then created buttons I did filter operations to only populate the items that satisfied the filter criteria. So, to illustrate, it looks like this:
const things = [
{continent: Asia, country: Korea},
{continent: Europe, country: France},
{continent: Africa, country: Egypt},
.....
];
const filter (continent) = > {
//Logic to filter based on continent criteria and return the countries
};
This was possible in vanilla JS, because I could set aside the array variable in the script document and the functions would easily reference it.
The question is: how do I do something similar in react? i.e. what would be an equivalent way to store a variable that lasts as long as the page is active, so that I can do filter operations on them? Obviously, setting aside a variable outside of the component doesn't work after the page is rendered. Where should I look to resolve this?
Any advice will be appreciated. Thanks!
For this you can either do one of three things
Pass an array defined at the top level between children and
parents (can work for simple pages)
Use the React Context Api
https://reactjs.org/docs/context.html
Look into a state management library like Redux (most recommended if your application is complex) -
https://redux.js.org/introduction/getting-started/
If I understand correctly, you want to write data on a page server-side, and then load it into a React component client-side. I would try writing the data into a hidden element, probably in csv format, with an "id". Then, when your App component loads, use document.getElementById to retrieve the data. Pass that into your component tree, and filter away.
Sorry, I'm not able to test this out at the moment. There may be some gotchas with this approach, but if you don't want to fetch the data client-side, hopefully something like this will work.
Related
tl;dr: Why not pass variables by reference between components to have them work on the same data instead of using e.g. BehaviorSubjects?
I'm writing a sort of diary application in Angular 8. I have two components (Navbar and Dashboard) and a service (EntryService).
Navbar lists the entries, Dashboard provides the textarea, EntryService glues them together and communicates with the database.
While debugging the application I stumbled upon a way to communicate between the service and a component that i haven't thought of before.
By accident I passed a variable (entry: Entry) from the Dashboard by reference to the EntryService. The service saved to the database getting a unique ID back and saving this ID into the entry variable. This change immediately reflected to the Dashboard because of the 'passing by reference'.
Until now I was using Subjects to update the components on changes, but passing references around seems to be much simpler, because I want to work on the same data on both components and the service.
I've studied Angular for a while now and not read about this approach, so I'm wondering if it is a bad idea or design and if yes why?
Thanks for your answers!
Passing by reference can be handy. But as a general approach to keep the application components in sync it has some draw backs. With Subjects you can easily investigate in which places of the application the value of the Subject will be changed by checking where the Subject.next() function is being called. When you pass your object by reference to a hundred components/services it will be much more difficult to find out, which of them modify the object and more importantly when, becaue often you want to trigger other changes afterwards. When you subscribe to Subjects, you get notifications about changes and can react to them. Subjects and Subscribers are an example for an Observer/Observable pattern, it allows you to decouple your application logic. And they are much more flexible, for example you can have a Subject which can return the last x number of changes or you can debounce the changes when you track user input, you can apply filters to them etc.
I'm trying to create a very basic key-based translation system since our system doesn't have to be as expansive as something like vuei18n. I'm simply loading a json with a key and each key has four translations. About a hundred items in total. Now; I'm using a seperate Translator window component that I link to Vue like this;
Vue.prototype.translate = function(key){
window.addEventListener('switchedLanguage', function(event) {
console.log(event.detail);
return window.translator.getTranslation(key);
});
return window.translator.getTranslation(key);
}
and in order to render them in the templates I do the following:
{{ translate('key') }}
I understand that connecting scripts like a translator directly to the window isn't the best of practices, but is what's working in the application right now.
The thinking behind it is that when the language is changed within the translator, it will try to get back the key. While this technically works, in the application I am not seeing the keys get re-rendered to the different language. I've been deep down the rabbit hole now and don't seem to get a clear answer why except for the fact that it's not bound to the data model. But for some of the components, they can have up to fifteen keys or more depending on input. It's not feasible to store all the keys in the data model of each component since that will, in my view, unnecessarily clutter the data model.
So, what I've tried so far is the following:
Use a filter with the key as an input (this results in Vue freaking the hell out because it can't resolve the filter since it isn't able to find the translator through Window.translator)
Reload the entire window (while working, very ugly solution since it takes the user back to the main screen)
So we are about two months in on a project. This is the first time I have ever managed code writers and not written the code myself. I've been reading their code for the last week. What was suppose to be a simple React app has turned into a spaghetti mess.
I understand: redux helps to manage global state. But should that mean that all buttons should map to a global "action?" This has seemed to create this entire mess of objects scattered throughout the entire app. I keep asking myself, why are we using global state for everything when local state could be used for 90% of the application. This is the kind of code that gives me heartburn:
let subitems = SidebarItems[state.type].sub_items;
Store.dispatch(SidebarSubItemHandler(item.action, subitems[0], null));
if(item.sub_items[subitems[0]].param) {
browserHistory.push(`${item.sub_items[subitems[0]].path}/${item.sub_items[subitems[0]].param}`);
} else {
browserHistory.push(item.sub_items[subitems[0]].path);
}
subItembuttons = Object.keys(this.props.subitems.sub_items).map(subitem => {
let subItem = this.props.subitems.sub_items[subitem];
return <li className={this.props.activeSubItem.action == subItem.action ? "bottom-bar-item active" : "bottom-bar-item"}
onClick={e => this.props.onClickSubItem(e, subItem)}
key={subItem.action} style={this.props.subitems.inlineStyles.mobileSubItemLI}>
{subItem.item}
</li>;
});
The application is littered with all kinds of objects like these that map to "action" objects. So at this point we are making the decision to scrap the entire project and restart from scratch, but without redux. Let's try to do as much as possible using local state only. When it comes time, and we need global state for something, ONLY implement it for that something, not every single action in the app. Does this make sense?
So I guess my question is: If we develop an app using local state and just fundamental React, will we be creating un-reversable problems that would prevent us from implementing redux on a per item basis?
Quoting from the relevant Redux FAQ entry at http://redux.js.org/docs/faq/OrganizingState.html#organizing-state-only-redux-state:
Using local component state is fine. As a developer, it is your job to determine what kinds of state make up your application, and where each piece of state should live. Find a balance that works for you, and go with it.
Some common rules of thumb for determing what kind of data should be put into Redux:
Do other parts of the application care about this data?
Do you need to be able to create further derived data based on this original data?
Is the same data being used to drive multiple components?
Is there value to you in being able to restore this state to a given point in time (ie, time travel debugging)?
Do you want to cache the data (ie, use what's in state if it's already there instead of re-requesting it)?
Per your specific question: if you use the "container component" pattern fairly consistently, it should be relatively straightforward to swap those "plain React" containers for Redux-connected containers down the line. See https://github.com/markerikson/react-redux-links/blob/master/react-component-patterns.md#component-categories for articles on the "container/presentational component" pattern.
Two other thoughts. First, I recently co-authored an article that discusses why you might want to use Redux in a React application.
Second: yeah, that code looks kinda ugly. I'm hoping those are at least three different snippets from different parts of the codebase, rather than one snippet, but that's rather hard to read. The repeated use of "sub_items" and "subitems" seems like a bit of a red flag, readability-wise.
It also doesn't look like it's following good Redux practices. For example, idiomatic Redux code almost never references the store directly. Instead, references to dispatch and getState are available via middleware, and thus can be used in action creators via redux-thunk and redux-saga. Connected components can also access dispatch.
Overall: you are absolutely welcome to use as much or as little Redux as you want, and as much or as little local component state as you want. I think the larger issue, though, is how well your team actually understands Redux, and how they're trying to use it.
Maybe at official flux website I saw a video were mentor said something like:
Only top-level React views should know about stores. All not top level
views should be dump and receive all information as properties.
Question: Is that right? Your argumentation, please
BUT, suppose you have some small React view Button.react that's reused on multiple pages. And suppose Button.react must know about some store data. If we won't fetch all data directly from the Button.react, we get a duplication of code at each top-level component which reuse Button.react. Is that ok for you?
I hope I am understanding your question.
One of the characteristics of React is its one-way data flow. Each component can be used by another component, just like one function can call another function. Just like a function, a React component should typically be able to get all the info it needs to do work (render itself) from the arguments passed into it. This is the function of props in React. When using Flux, sometimes the React Components, which are typically near the top of the view hierarchy, that actually fetch the data from the stores to pass down thru the application are called Controller-Views.
It is not an enforceable rule that every component doesn't become a Controller-View, getting its own state directly from a store, but it is a general practice for good reason. consider the two functions:
function renderToggleButton( isSelected ){
//... render the button
}
vs
function renderToggleButton(){
var isSelected = StateStore.getButtonSelectedState( id );
//... render the button
}
I think you will agree that the second function is more complicated and difficult to test. It has to know from where it is getting it's initial conditions. It also has to know how to identify itself in the context of the application. These are two things the function should not have to know.
Now imagine an application full of functions like this. If one function is misbehaving, it becomes very difficult to trace its inputs; to test it under controlled conditions. I hope that clarifies the guidance given for passing data thru the application as props.
Suppose I have a Javascript game that draws on a HTML5 canvas, it loops through updating and drawing a bunch of objects. What's the best way to go about saving the current state of the game? I guess I could loop through all the objects and write all values in text form in a format that can be read by a loading function, but that seems like quite a lot of work for both me and the game, as well as a large save file size. Is there a better way to do this? I've never done something like that before, I don't really know where to start.
Thanks.
A standard practice for something like this is to maintain a data model which represents your system, and a view that represents your model. The model should be mostly data, which can be relatively complex, but it has all the information necessary for your view to render.
Assuming this model is an object tree, you can just call var serialized = JSON.stringify(model) to serialize your data model to a string and then var model = JSON.parse(serialized) to get it back. This is a very simple, yet inflexible approach, but it is a start.
A quick way to store this information would be with localStorage but you will likely want to move to a back-end storage where you are putting values up to a REST service (or something like that) so that this data can be retrieved from anywhere.
I recommend looking into MVC-like frameworks like Backbone.js (for instance) which helps you to separate your models from your views, and also does a great job of persisting/hydrating your data from your data store.
You'll want to do some research on the keyterms of 'serialize' and 'unserialize'.
Instead of doing a recursive loop on every object, I'd suggest that you have all your game objects implement a function for serialization. You can use JSON to build up your entire object tree, with each object deciding what properties need to be kept, and which properties can be derived from the rest. While this does appear to do the same thing as a recursive loops on some levels, the huge difference is that each object can define, on it's own, how to serialize/unserialize itself and it's contents..
Depending no how precisely you want to save your game state, you can reduce a LOT of data that way. For example, maybe you can simply reset them to the beginning of the current level, or you could dump some data that's available elsewhere (level data, for example, probably shouldn't be stored in the save file, only the information on game state that lets you reproduce the level using your existing level data store).