passing data between two child component without shifting up state - reactjs

I am working on the interface with react. As soon as a button in the 'Buttons' area is clicked, the expression in the 'filter text input' must be used to query a REST interface which returns a list of items as JSON. This data must be passed to the lower left panel to update a tree view.
The 'filter text input'+'Buttons' is a controlled input.
+-------------------------------------+
| +-------------------------+-------+ |
| | filter text input |Buttons| |
| +-------------------------+-------+ |
+----------+--------------------------+
| + item1 | +---------------+ |
| | +-... | | text input | |
| + item2 | +---------------+ |
| | +-... | +---------------+ |
| + item3 | | text input | |
| | +-... | +---------------+ |
| + item4 | |
| | +-... | ... |
+----------|--------------------------+
The canonical approach according to all the tutorials and documentation is to shift the state up to the common parent. However, this is a pretty bad idea because with every single key stroke the whole view will be updated entirely, including the tree in the left panel.
Is there a generally accepted way (and good practice) to exchange data between components that belong to the same parent without shifting the state upwards or is there any other approach?

I see two options:
Stick with the current approach (which sounds legitimate and straightforward), but utilize shouldComponentUpdate to prevent unnecessary updates.
Use a central data store. Check out Redux.

If you have properly put your code together, there should be no performance concern here, and no need to use a centralized data store such as Redux.
However, this is a pretty bad idea because with every single key stroke the whole view will be updated entirely, including the tree in the left panel
Have you tried? If the rest of your tree does not change, React will realise this when traversing the two virtual DOM trees for changes, and will not re-render what has not changed. Unless you are incorrectly using the key prop and forcing a re-render, this will not happen, as the sub-trees are all the same.
It is true, however, that the render method is being called on all of those sub-components. The best way to prevent this, as mentioned by Or B, is to use shouldComponentUpdate; something like the following:
shouldComponentUpdate(nextProps) {
if (this.props.propA !== nextProps.propA) {
return true; // re-render
}
return false; // don't re-render
}
You can do a full-scale check quite easily using the PureComponent class, like so:
import React, { PureComponent } from 'react';
class MyClass extends PureComponent {
...
This does a shallow check of all of the props being passed to the component. The same functionality can be achieved using the pure method of recompose, like so:
import { pure } from 'recompose';
class MyClass extends Component {
...
}
export default pure(MyClass); // same thing, really; just a bit more overhead

You have to be careful with the way you pass callbacks. If you pass them as arrow functions a different callback is created each time the component is rendered. From the documentation: "However, if this callback is passed as a prop to lower components, those components might do an extra re-rendering. We generally recommend binding in the constructor or using the class fields syntax, to avoid this sort of performance problem." See https://reactjs.org/docs/handling-events.html for more details.

Related

Is there a way to hide components from vscode auto import suggestion?

I've a generic react component called DatePicker, and at the same time I also have an internal component called DatePicker too
|- Components
| |
| |- DatePicker
|
|- Screens
| |
| |- MyScreen
| |
| |- DatePicker (I want to exclude this)
Now I would like to exclude the internal component from the vscode import auto suggestion... Is there a way?
How do you handle cases of this type?
There is no method to conceal components from auto-import in vscode. It's preferable if you type the import yourself, but you may also use the shortcut Ctrl + Space and there should be two DatePicker on the options for you to choose from.

How to restrict to React.Fragment of certain children types?

I have a component that I have typed with flow, and it only allows certain types of elements, a very restricted list.
Now I need to expand it to also accept a Fragment so we are able to do some render logic and group children. However, I only want to take Fragments containing an specific subset of valid components, just like the normal type.
So this is what I have now:
type ValidChilds =
| item
| header
| separator
type PropsA = {
className?: string,
children: ChildrenArray<Element<ValidChilds>>
}
As I said, this works very nice to restrict the children.
So what I want now, is to be able to accept this:
<>
<item>
<header>
</>
but not this:
<>
<other>
</>
I tried this, but it is not working:
type ValidChilds =
| item
| header
| separator
| AbstractComponent<{ children: ValidChilds }, typeof React.Fragment>
type PropsA = {
children: ChildrenArray<Element<ValidChilds>>
}
After looking at the React.Fragment definitions, I gave it a try, but it looks like it's not possible currently, as we can't override the core Fragment statement definitions.
Might be worst opening an issue as it's definitely a useful case.

Why do we have to define states in root component?

I'm learning React. I don't understand why we have to define states in the root component a.k.a in App.js .
İf I have a card component and I only have a state related to the card component should I define it in root component or card component? Can you help me to understand this logic?
Thanks for the answers
Each component can have its own local state. There is no such thing as "You should define your state in App".
It's different than a global state which will need a different approach depending on the library you are using, but since you are learning react you will comme across this soon with the context Api, Redux, MobX, etc.
For your card example, you can have a local state in your card component, but you might want to manage your array of cards' data in the parent (Not App, just one layer above) if you need to do operation like sorting/filtering your cards for example. It just depend on what you need to do with your data.
The reason for declaring React states in the parent components rather than the children component is when the state somewhat relates to multiple components at once.
For example, take a look at this structure:
+--------------------+
| App.js |
| +----------------+ |
| | Title.js | |
| +----------------+ |
| |
| +----------------+ |
| | Description.js | |
| +----------------+ |
+--------------------+
And here's our data:
const getData = () => {
return {
title: "some title",
description: "some description"
};
};
If you're trying to render this data with the structure we have, then the state has to be on the App.js layer and we'll need to pass the data into <Title/> and <Description/>.
In your example, if the state is strictly for the Card component, you should be able to declare a state inside the Card component without any issues.
In my opinion, states should only need to be on the parent level if they're being used in multiple children.

What's the most appropriate folder layout for a react frontend? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
Recently, I've taken an interest in React as I believe that it'll allow me to hopefully get a job in the near future. I already know Laravel PHP fairly well but that doesn't seem to cut it when it comes to looking for jobs.
I've so far, managed to make a single page twitter clone an I will hopefully be using firebase to store and return tweets.
I would also like to add multiple pages and perhaps some sort of authentication system.
However, in order to do that, I need to do utilize react's router.
My current folder setup looks like
this.
For an app that only has one page this works well, however, I am unsure as to how it would work with multiple pages and how I should lay that out.
For example, should I have a folder called, pages? Then have a folder for each page an then within those pages, the Page.js component and then a components folder for that page? That's my current thinking but I am totally clueless on the best way to deal with this.
I think it would be cool if i could have one big folder which stores all components so that I can reuse them whenever I want.
Thanks in advance.
The key to creating a "good" react app is abstraction. If a component is doing two things, break it down into two components. The idea here is that you will start to notice redundancies in your components where you can turn similar components into a single component used multiple times. This is also why thoroughly planning out your application beforehand is best.
With all this in mind it is best practice to have a dedicated "Components" folder in the "src" folder. At the top level this will contain commonly reused UI components (lists, modals, cards, buttons, etc.). Each of these component folders is capitalized and will also store any "sub-components." An example of a sub-component would be a drop-down menu component within a header component. Each components folder will look something like this:
components
| Header
| | DropDownMenu
| | | index.js
| | | style.css
| | NavButton
| | | index.js
| | | style.css
| | index.js
| | style.css
In addition to a components, create folders for groups of higher level attributes or libraries; for example a "pages" or "routes" folder which houses the apps different pages. Another good example is a separate folder for Redux to manage actions, reducers, and storage... or maybe a media folder for local images and svgs.
Here is a simple template for a small react app's folder structure:
src
| firebase
| | firebaseConfig.js
| components
| | Component
| | | SubComponent
| | | | index.js
| | | | style.css
| | | index.js
| | | style.css
| media
| | images
| | | image.png
| | svgs
| | | image.svg
| pages
| | Home.js
| redux
| | actions
| | | action.js
| | reducers
| | | reducer.js
| | store.js
| | types.js
| App.css
| App.js
| index.css
| index.css

Props or State for an editor of tree-like data structure

The app is for user to create a tree-like structure. The tree node is defined:
// This is a node
{
images: [{x:0, y:0, width: 100, height: 100}, ...],
subnodes: {key1: [<node>...], key2: [<node>...]}
}
The UI looks like
+----------+----------------------------+
| | |
| Tree | +---+ |
| Overview | | | +--------+ |
| | | | | | |
| | | | +--------+ |
| | +---+ |
| | |
| | drag drop to resize |
| | and position |
| +----------------------------+
| | |
| | some options for leaf |
| | |
| | |
+----------+----------------------------+
The left hand side is the total data-structure as result. The right hand side is for editing node selected in left hand side.
The question is, should I use node data as props or state for right hand side?
Using state is easier to modify the node data, but the risk is inconsistent, because it violates single source of truth.
If I use props for top-right component, I have to propagate drag event to right component and then prop to top most component, and then modify data.
As long as a component needs to alter itself, it should go into state. If not, it should go into props which you can se more as a configuration of a component.
In your case I believe the node data you are currently working with should live in the top-right components state, while you move things around and the component has to alter itself. When you are done, update the source data using an update function passed down as a prop from the parent component, and let the data flow down through the components again.
The state less, or dumb, components that rely completely on the props they receive, and will only update if they change, should in my opinion be used for simple things in the end of the data flow. More complex self altering components like your drag/drop/resize component should handle it's own state while active.
Hope it helps!

Resources