Passing props with React Router - reactjs

So I'm still learning React, but I feel like I understand at least the "basics". However, Routing with React router and just general "architecture" is where I'm getting a little lost at.
I'm making a personal project app, but ill keep my descriptions/components generic for the explanation. Essentially I have 3 Main components right now:
<Table/> (Rendered in "App" and also the main / URL route, it's essentially just a bootstrap table. Also contains my state which is an array of objects (That will be eventually retrieved via JSON via a GET request to an API)
<Row/> (A single row of data on the table, represented by 1 object in the array of objects from the state provided in <Table/>. Also contains a button that takes you to the "View" page/component below)
<View/> (What is going to be a "View/Details" page for the Row)
So I imagine my route for <View/> is going to be something like <Route path="/:id/view" children={<View/>} /> (Keeping it super simple and generic right now just for the explanation)
Sidenote: How come sometimes I see <Route> wrapping a component and sometimes I see <Route> defined with the children prop pointing at the Component to render?)
Anyways...the button in <Row/> will be a <Link to={'{$props.id}/view'}> I think....however how exactly do I pass the props down to <View/> based on the :id param? I need to pass the data I receive in the <Row/> component onto the <View/> component (Because within the <Row/> component is where I link to <View/>.
I suppose ONE option would be to do something like let {id} = useParams(); and then do a GET request specific for that particular resource from the API. But considering I'm already passing the data down to each row and it's available in the state within <Table/> it seems like an unnecessary HTTP request.
Im probably making this more complex than I need to, but I need to pass the "data" all the way down from <Table/> to the <View/> component depending on the data id. And I'm not really sure how to set up React router to do that. Hopefully what I'm asking makes sense.

To answer your first question, I'll reference the react-router documentation as this is answered in the subsection named "route render methods".
The tldr of the above is simply that the "preferred" method of rendering components via <Route/> is by supplying actual children to the component. However, there are other methods and specific use cases that go along with each.
As for the core issue you're asking about: What you'll want to do is use an object in the <Link /> component that persists a state to the <View /> element that has all of the information that it will need. You can find react-router's documentation on this here.

Related

React Router - What is the difference between Route children and component props

I've got some troubles understanding what's the diferrence between this:
<Route path="user/:id" component={UserComponent} />
and this:
<Route path="user/:id" children={<UserComponent/>} />
inside Switch component when using React Router.
In both cases those components will render if the url will look like this "/user/4322". I'm reading React Router documentation but I can't understand this use case correctly (https://reactrouter.com/core/api/Route/route-props)
Okay, I got it:
https://forum.freecodecamp.org/t/react-router-what-is-the-difference-between-route-children-and-component-props/429503
#DanCouper from FreeCodeCamp forum explained it perfectly:
the first one is if you want to mount a new component when the route
matches. This is what things most often look like: you have a set of
routes and they all open a new “screen”, last component unmounts, new
component mounts, everything gets blown away. It’s the simplest way to
do things.
second one is if you want something to render all the time and not
remount. So for example, as in the example in the docs, you have a set
of navigation links, and you want to animate between them on route
change. If you used component this wouldn’t work, because the new
component would mount every time and the animations wouldn’t happen.
But because children is used, can still have the URL change in the
browser but not have everything be blown away every time the URL
changes.
children (and render) are going to be more fiddly to use most of the
time, because they cater to less common scenarios (in children's case,
preventing new component creation every time routes change, allowing
the UI to dynamically change based on route).

React Router: Selective route props passing to children

Consider the following example:
return (
<Router>
<Route component={Table} path='/table' />
</Router>
);
Let's assume we're on the /table route the entire time.
Whenever the URL changes, the Router will re-render one of the Route components (even when the path doesn't change, see: https://github.com/ReactTraining/react-router/issues/7539).
My users like to share the URLs with each other and expect the displayed page to be more or less the same. Therefore, I need to store some information into the URL, e.g. /table?country=Narnia. The problem is, when I append or edit the search query, the child component will be re-rendered (because the search inside props.location changed), which will in turn trigger the update of its children and so on. In truth, only a part of the page needs to take into account this change inside the URL, e.g. table might apply some sort of filtering logic to the data.
What is the best way to achieve this behavior? I am talking about the likes of useSelector in Redux or Context Provider Pattern with React's Context.
Using useLocation/useMatch in nested children will also result in unwanted renders - one component might be interested in changes to parameter country, but some other might want subscribe to parameter age. useLocation would cause both to re-render when the url changes.
I am trying to avoid writing custom useEffect to control rendering of components subscribing to route changes.

How to pass a property to a component via the reactjs router?

I have a reactjs router v2.8.1 in my app and trying to figure out how to pass properties to a component. This is what one of the routes looks like:
<Route path="/comp2" component={Component2} />
Suppose I am trying to go from Component1 to Component2 and want to pass properties from Component1 what would be a way to do this?
If you are using MemoryRouter or NativeRouter, you can send arbitrary state as explained here.
For web though, you should prefer taking dynamic data as either query params, or url parameters, as depicted in the links. The reason being that these are stored right within the address. This allows some more browser scenarios (e.g. bookmarks, in-private mode) to work as expected.

Reactjs - data flow

I have a general question about where to load data in Reactjs.
The main component is called App. Then the App returns 3 components: Header, Body, and Footer. Now within Body, there is a Tab component, which is further subdivided into a few components including a component called "grids".
Now I want my data (after being filtered) displayed in Grids.
Please correct me if I'm doing it wrong but my thinking is:
Load data in the main component App as state:
Pass it to Body with:
<Body data={this.state.data} />
In the Body component, pass it further as:
<Tabs data={this.props.data} />
In the Tabs component, pass it further as:
<Grids data={this.props.data} />
In Grids, write all the methods to filter data and display/return it accordingly.
Is this correct?
Thanks
The flow you've outlined is correct. An alternate approach is to use context: Anything set into context of one component is available to every descendent of that component, without setting props of intermediate components.
Context comes with a warning though:
Using context will make your code harder to understand because it
makes the data flow less clear. It is similar to using global
variables to pass state through your application.
BTW, for managing data, I'd use something like Flux or Redux. Managing data directly within React components quickly becomes a pain in a** as application grows. Flux/Redux, on the other hand, scale very well.

ReactJS: Why use this.props.children?

I've realised that none of the components I write use {this.props.children}.
I tend to compose my components the way the official docs state at the top of https://facebook.github.io/react/docs/multiple-components.html.
Is nesting the components like this...
<A>
<B />
<C />
</A>
...beneficial over composing them like this?:
A.js
render() {
<B />
<C />
}
Presuming that's the right terminology, what am I missing?
In my applications I rarely use this.props.children, because I often know specifically what children I want to render. In libraries, or components written to be re-used outside of a specific component hierarchy, I've seen it often. I think this.props.children has more relevance to that use-case.
Edit: I thought I'd elaborate on some cases that this.props.children can come in handy. One such example is when creating components which follow the 'render prop' pattern. i.e. I've got some components that require pulling data in from multiple 'render prop' HoC's, such as an Apollo Query component as well as a state management HoC. I combined all my different data sources into one HoC and then called children as a function, passing in the result of pulling out all the data I needed. That being said these days I prefer and look forward to wider adoption of Hooks as an alternative to render props.
Really any component which you want to render arbitrary children; another example I've used props.children is when creating a HoC that required a user be authenticated before rendering the child, redirecting to a login screen when the user isn't logged in. I could wrap any of my 'protected' screen components with this auth HoC.
It's still something the majority of my components don't use, but just another tool to be applied when the situation warrants.
I'd say it would be useful when you don't know what you want to render.
For instance, you have a tooltip wrapper, let's say it's A component in your scenario, and you can use it to pass different content:
<A>
<div>Some text...</div>
<ImageComponent /> // render an image as well
</A>
Or:
<A>
<div>Only text</div>
</A>
Some components don't know their children ahead of time. This is especially common for components like Sidebar or Dialog that represent generic "boxes".
We recommend that such components use the special children prop to pass children elements directly into their output:
Read More...
Children is a special prop that can be passed from the owners to the components defined inside their render method. It allows us to customize a structure of a component.
With props, a child component keeps its structure under the full control and only certain attributes or values are allowed to be passed. The structure of the component is hard coded.
In the React documentation, children property is described as opaque, because it is a property that does not tell anything about the value it contains. As a result it allows a client/parent to customize a structure.
We can also say, that the components defines only a kind of basic template/structure, for instance by providing a kind of "header". And the consumer reuses this header structure, by adding children.

Resources