I have a router config like this:
<Router history={browserHistory}>
<Route path="/">
<IndexRoute component={HomePageContainers} />
<Route path="r/:subreddit_name" component={Subreddit} />
</Route>
</Router>
HomePageContainers renders like:
render() {
return (<div>
<HomePage reddits={this.state.reddits} key={this.state.isLoaded && this.state.reddits.data.after} isLoaded={this.state.isLoaded} isScrolling={this.state.isScrolling} scrollFunc={this.onScroll.bind(this)} />
</div>)
}
and HomePage render Reddits like:
<Col md={3} key={reddit.data.id}>
<Reddits key={reddit.data.id} reddit={reddit}/><br/>
</Col>
There is a Reddits class which looks like:
class Reddits extends React.Component {
constructor(props){
super(props);
}
render() {
let reddit = this.props.reddit;
return(
<div id={styles.box}>
<p>{reddit.data.title}</p>
<Link to={reddit.data.url}>
<p>{reddit.data.url}</p>
</Link>
</div>
)
}
}
whenever the path is r/:subreddit_name made, Subreddit component gets life and its working. Here I also get the :subreddit_name value as part of routeParams. But if you look at the Reddits class, the reddit.data has all the information for Subreddit.
I want to send the reddit.data as props from Route(r), is it possible?
You will want to have HomeComponenet render your Reddit component as children like so:
<Route path='/home' component="HomeComponent">
<Route path='/reddit' component="RedditComponent">
</Route>
To get reddit component to display you need to render children in your HomeComp:
render() {
{ this.props.children }
}
Now you can pass in props via cloning children like so:
HomeComp:
render() {
{this.props.children && React.cloneElement(this.props.children, {
someFunctionOrDataToPass: this.someFunctionOrDataToPass
})}
}
Here is another example
Related
I would like to hide a component when another component is routing
for more specific, i have a fixed bottom nav that i want to hide when a component is been route by user, in this case its a comment box
My first option was trying on the parent component with browserhistory and history.listen, and componning a string with math.params for get a match between, and this change the state of parent, witch will hide the bottomnav, and the code wrote was trying through a cyclelife passing props, but nothing, anyone can help me please?
class App extends React.Component {
constructor(props){
super(props);
this.state = {
showBottomNav: true
}
this.hideBottomNav = this.hideBottomNav.bind(this)
}
hideBottomNav= () => {
this.setState({
showBottomNav: false
})
}
render() {
return (
<Router>
<NavBar />
<Switch>
<Route path='/' exact component={Home} />
<Route path='/wars' exact component={Tournament} />
<Route path='/shop' exact component={Shop} />
<Route path='/library' exact component={Library} />
<Route
path='/:id'
exact
render={ props => <ExpandedPost {...props} parentMethod={() => this.hideBottomNav()} />}
/>
</Switch>
<BottomNav />
</Router>
);
}
}
export default App;
And the children Component
export default function PostReview(props) {
const classes = useStyles();
useEffect(() => {
props.parentMethod()
},[props])
return (
<div>....
The app.js file of my project is following. For all other components I used this.props.history.push('/') to redirect to the specific path and it works as those components receives the props. But in this app.js I have tried to console the props values inside constructor, componentWillMount and render but all gives null array. Is there any way to use this.props.history.push('/') inside app.js ?
class App extends Component {
constructor(props) {
super(props);
this.state = {};
console.log(this.props)
}
componentWillMount(){
console.log(this.props)
this.props.history.push('/')
}
render() {
console.log(this.props)
return (
<Router>
<div className="App">
<Route exact path='/' render={(props) => <Login {...props} />} />
<Route exact path='/dashboard' render={(props) => <Dashboard {...props}/>}/>
</div>
</Router>
);
}
}
export default App;
use withRouter
import { withRouter } from 'react-router-dom'
class App extends Component {
constructor(props) {
super(props);
this.state = {};
console.log(this.props)
}
componentWillMount(){
console.log(this.props)
this.props.history.push('/')
}
render() {
console.log(this.props)
return (
<Router>
<div className="App">
<Route exact path='/' render={(props) => <Login {...props} />} />
<Route exact path='/dashboard' render={(props) => <Dashboard {...props}/>}/>
</div>
</Router>
);
}
}
export default withRouter(App);
that will give you access to the history object and allow you to push to new routes. (I tested and verified before posting, so I know this works).
import it on the top of the file, then wrap App with it in the export default
I am rendering a Home component inside a Route so that I can pass state in as a prop to the component.
class App extends React.Component {
constructor(props){
super(props)
this.state = {
page: 'false'
};
}
render() {
return (
<Router>
<div>
<Switch>
<Route exact path='/' render={()=><Home page={this.state.page}/>} />
<Route exact path='/projects' component={Projects} />
<Route render={function(){
return <p>Not Found</p>
}} />
</Switch>
</div>
</Router>
)
}
}
Inside the Home component, I want to trigger a route change from a function. Because the Component is rendered inside the Route the history prop doesn't get passed in and therefore I cannot trigger a route change like so:
class Home extends React.Component{
constructor(props){
super(props);
this.gotoProjects = this.gotoProjects.bind(this);
}
gotoProjects() {
this.props.history.push('/projects');
}
render() {
return (
<button onClick={this.gotoProjects.bind(this)}>Projects</button>
)
}
}
How can I change routes from a component while still retaining it's props?
UPDATE
I've created a History.js using createBrowserHistory
import { createBrowserHistory } from 'history'
export default createBrowserHistory()
And updated App.js to be
import history from '../history';
class App extends React.Component {
constructor(props){
super(props)
this.state = {
page: 'false'
};
}
render() {
return (
<Router>
<div>
<Switch>
<Route exact path='/' render={()=><Home history={history} page={this.state.page}/>} />
<Route exact path='/projects' component={Projects} />
<Route render={function(){
return <p>Not Found</p>
}} />
</Switch>
</div>
</Router>
)
}
}
So now when I click the button in Home the url goes to /projects but the view is still rendering Home instead of Projects. How do I render Projects after the history.push happens?
I have set the state in a component as follows:
class App extends Component {
constructor(props) {
super(props)
this.state = {
minutes: 3,
interests: {
business: false,
code: false,
design: false
}
}
}
render() {
return (
<div className="App">
<div className="content">
<div className="centered-wrapper">
<Switch>
<Route exact path="/" component={Welcome} />
<Route path="/life" component={Life} />
<Route path="/work" component={Work} />
<Route path="*" component={Welcome}/>
</Switch>
</div>
</div>
);
}
}
export default App;
And I'm trying to use the state in one of the components managed by the router in the following way:
export class Welcome extends Component {
constructor(props) {
super(props);
this.state = {
errors: []
};
}
render() {
return (
<form className="Welcome">
<input className="minutes" type="number" defaultValue={ this.state.minutes } /> minutes.
</form>
);
}
}
But it doesn't work. Is state not global by default?
State is only available inside the component which defines it. If you want to use state in another component, you have to pass it using props.
To pass props along with your Route, you can use the render function.
You can then call your component using:
<Route exact path="/" render={props => <Welcome {...props} minutes={this.state.minutes} />} />
And then in the Welcome components use the passed minutes prop instead of state.
I have react router setup with route parameters :name
<Router>
<Switch>
<Route path="/" exact={true} component={Index} />
<Route path="/about/:name" component={About} />
<Route component={NotFound} />
</Switch>
</Router>
Using <Link to=, links from Index correctly route to eg /about/vinnie.
However, if the <Link to= component is on the About page, clicking the link merely updates the browser URL, but dies not re-render the correct page.
Any clues why this might be happening?
About.jsx
render () {
const id = this.props.match.params.name;
return (
<div className="Explore">
<div className="container">
<Api endpoint={[this._apiEndpoint(id, 'info')]} loadData={true}>
<CustomerInfo />
</Api>
...
Api.jsx
render () {
let showData = this.props.loadData ? null : <button onClick={() => this._loadButton()}>Show</button>;
return (
<span>
{this.props.children && React.cloneElement(this.props.children, {
apiData: this.state.rawData
})}
{showData}
</span>
);
};
CustomerInfo.jsx
class CustomerInfo extends React.Component {
constructor(props) {
super(props);
this.state = {
CustomerInfo: {}
}
}
componentWillReceiveProps(nextProps) {
if (this.props.apiData !== nextProps.apiData) {
this.setState({CustomerInfo: nextProps.apiData[0]});
}
}
render() {
...
I think you need to add the exact prop to your first <Route />. Otherwise your routes match Index and About and I think react-router intentionally renders both.