I am using react-router(v3) for routing purpose in my app. I have some nested route and want to access parent component state in child component.
Route:
<Route component={Main}>
<Route path="home" component={Home} />
</Route>
Main Component(parent):
export default class Main extends Component {
constructor(prop){
super(prop);
this.state = {
user : {}
}
}
render(){
return (
<div>
Main component
</div>
)
}
}
Home Component(child):
export default class Home extends Component {
constructor(prop){
super(prop);
}
render(){
return (
<div>
Main component
want to access user data here. how to access user from parent component?
</div>
)
}
}
In Home component i want to access user data, that is in parent component Main. Is there any way to access parent component state in child component ?
Your problem is that you can't just pass user as props to Home because App is not direcly rendering Home. You're doing that through React-Router.
You got 2 approaches here:
Use a state management solution like Redux and connect() both Main and Home to the user in store. This way, user is not part of Main state, but part of the app store and can be accessed from other components. This is the most sophisticated / extensible solution.
Use Contexts. From the docs: In some cases, you want to pass data through the component tree without having to pass the props down manually at every level. You can do this directly in React with the powerful "context" API. If you want to avoid using Redux or Mobx or any state management this may be the way to go.
send state of parent component as props to child component.
within Parent component fetch child like this...
<Home user={this.state.user} />
Access user in child by this.props.user
Related
I have an app that was written mainly with class base react components, however we are implementing a paywall feature with Stripe.
The issue is stripe uses hooks, which don't work with class base components. Is it possible to put a child class base component into a parental function base component in order to achieve this. How would I go about doing this without rewriting every component as a function base component.
Every attempt to include a function base component with class base children always yields this error:
Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
Are there any work arounds, or should I re-write the all the components as functional components?
A quick example using react-router-dom for query parameters, then passing those into a class base child component.
function useQuery() {
return new URLSearchParams(useLocation().search);
}
const App = () => {
let query = useQuery();
return (
<Provider store={store}>
<Router>
<div className="App">
<Navbar />
<Switch>
{/* Public Pages */}
<Route exact path="/" component={Landing} ref={query.get('ref')} />
</Switch>
</div>
</Router>
</Provider>
)
}
export default App;
Then assuming that the landing components is a simple class base component that will set the prop into the state.
Component's type doesn't matter in relation parent-child. But you can't use hooks inside of classBased component. Only in functional ones
Here is the code example of Functional Component as Parent and Class as Child
import React , {Component}from "react";
import "./styles.css";
const App = () => {
return (
<div className="App">
<h1>I Am Parent Functional Component</h1>
<Child />
</div>
);
};
export default App;
class Child extends Component
{
render(){
return(
<h2>I am Class Child Component</h2>
)
}
}
Okay I figured out the issue with this problem. Since I found the same question unanswered on the internet, I decided to answer the question myself, Just for future reference for anyone looking for the same solution I was running into.
You can use Hooks on a parental Function Base Component and pass on the information into a child base component.
While rendering the application, I was given an error
Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
However this error was due to outdated modules in npm. I just updated the react-router-dom from 4.1 to 5.2.0 npm update react-router-dom and it seem to solve the issue of using functional base component as a parent.
After updating the module I was able to use a hooks in a parental function base component and pass that on to a child class base component using props.
I am developing a web application using React JS. Now, I am trying to programmatically redirect to another route. I can redirect like this.
this.props.history.push('/event/${this.props.id}/edit');
But when I use that in the child component it is not working. This is my scenario. I have a parent component called, EventListComponent. Inside that component, I render another child component called EventWidgetComponent. I am redirecting in the child component. But this.props.history is always undefined when I use it in the child component. How can I fix it?
This is happening because your child component doesn't have the access to history. Child component is receiving the props from parent component not from Router, that's why.
These are the possible ways to solve the issue:
1- Either pass a method from parent to child and do the redirecting part inside parent component. Call that method from child component for redirecting.
2- Use withRouter hoc and render the child component inside that, it will provide access of history to child component.
Like this:
import { withRouter } from 'react-router-dom'
// Child component here
class Child extends React.Component {
// code
}
export default withRouter(Child)
Check this answer: Programmatically navigating in React-Router v4
3- Pass the reference of history to child in props:
<Child history={this.props.history} />
You can pass the history prop down from the component you are giving to a Route to the child component if you want to use it there.
Example
class App extends React.Component {
render() {
return (
<div>
{/* ... */}
<Route exact path="/" component={Parent} />
{/* ... */}
</div>
);
}
}
class Parent extends React.Component {
render() {
return (
<div>
<Child history={this.props.history} />
</div>
);
}
}
you can pass a prop to the EventWidgetComponent passed from the parent EventListComponent like onHistoryPush:
<EventWidgetComponent onHistoryPush={() => this.props.history.push('/event/${this.props.id}/edit')}
I am having nesting as follows with switch using react router 4
<MainComponent>
<ChildComponent></ChildComponent>
<ChildComponent></ChildComponent>
<ChildComponent></ChildComponent>
<MainComponent>
On main component page i am having some state which i want to pass as props to this.props.children.
In Main component render method i had written {this.props.children} to access children component. Now how to pass my CustomProps to this.props.children
Thanks in Advance for help
Suppose your state is day:monday.then you need to pass the state in child as
<MainComponent>
<ChildComponent day={this.state.day}/>
<MainComponent>
And in your child component ChildComponent you can get your state using
this.props.day
Trying to clean my React app up a little with Container and Presentation components. I'm using react-router v4 and I previously used an onClick event for each job to show a specific job page:
<div onClick={() => this.props.history.push('/jobs/' + job.slug)}>
//The job info
</div>
Now I've created a dumb component in a separate file for the jobs like this:
const Jobs = (props) => (
<div>
{
props.jobs.map(job =>
<div key={job.slug} onClick(//todo)>
<p>{job.title} at <Link to="/">{job.company}</Link></p>
</div>
)
}
</div>
)
but I can no longer access this.props.history
How can I solve this issue? Should I pass another prop in the following:
<Jobs jobs={jobs}/>
To access router objects(match, history and location) via props of the component, either the component has to be rendered via Route or it should wrap with withRouter higher-order component.
Check whether your Jobs component is directly rendered via Route with something like this.
<Route path="/jobs" component={Jobs} />
If it's not the case, and Jobs component is rendered with JSX inside the render method of another component, then wrap it with withRouter higher-order component as follows before you export it.
export default withRouter(Jobs);
This will ensure that Jobs component has access to all the router props.
Also, make sure that you use props.history instead of this.props.history since now it's functional component.
I have this setup in my app
<App>
<DynamicView />
</App>
App should render the title property of its child DynamicView.
I've tried
<h1>{children[0].props.title}</h1>
But that property is empty because the the DynamicView is a connected Redux component. So the actual react tree looks like this:
<App>
<Connect(DynamicView) ...>
<DynamicView title="A Title"/>
</Connect(DynamicView)>
</App>
Does connect provide a way to access its connected components properties?
One way you can accomplish is by accessing the child's children:
<h1>{children[0].props.children[0].props.title}</h1>
However, this goes against the React philosophy of parent components being isolated from their children.
An alternative approach that is more in line with React/Redux principles is to put the title in the redux store (and it looks like you already did that, considering DynamicView gets it as a prop). You could make the App component a connected component that grabs the title from the store, and passes it as a prop into App.
class App extends React.Component {
render() {
return (
<div>
<h1>{this.props.title}</h1>
<DynamicView />
</div>
);
}
}
export default connect(
state => ({
title: state.title
})
)(App);