I'm passing parameter from react-router's route path to component but in this.props object, 'params' not existing
const routes = (
<Router forceRefresh={true}>
<div>
<Route exact path="/" component={Firstpage}/>
<Route exact path="/projects" component={Projectslist}/>
<Route exact path="/projects/:projectId" component={Singleproject}/>
</div>
</Router>
);
And this is my component:
class Singleproject extends React.Component{
constructor(props) {
super(props);
}
componentWillMount(){
window.document.title = "Wploper | Project title";
}
render(){
return(
<div>
<Mainheader/>
<div id="single-project-container" className="sheet-max-width">
<h2>{this.props.params}</h2>
</div>
<Mainfooter/>
</div>
);
}
}
And the object (this.props) hasn't params:
enter image description here
tested for react-router v4
in your Singleproject component you can get the params by :
this.props.match.params.projectId
below is a code sample :
class ForgotPassword extends Component {
constructor (props,context){
super(props,context);
this.state={
busy : true,
sessionId : localStorage.getItem('sessionId') || null,
resetKey : this.props.match.params.resetKey || ''
};
console.log(this);
}
}
In react-router version 4 you can get the path params with this.props.match.params
You can get the parameter from the route through context.
this.context.params.projectId
Related
I want react route to match for localhost:8945/?type=admin adddress.I tried with following code but it is always rendering Home component.
<BrowserRouter>
<Switch>
<Route exact path = "/?type=admin"> **this is not working**
<Admin />
</Route>
<Route exact path = "/">
<Home/>
</Route>
</Switch>
</BrowserRouter>
Whenever I type localhost:8945/?type=admin in url bar it should render Admin component (Without requiring any server api).
got solution !
class App extends React.Component{
constructor() {
super();
this.state = {
type:''
};
}
componentDidMount() {
this.setUrlParams();
}
setUrlParams(){
const urlParams = new URLSearchParams(window.location.search);
this.setState({type : urlParams.get('type')})
}
render(){
return {
<div>
{ this.state.type=== 'admin'
? <Admin/>
: <Home/>
}
</div>
}
}
}
Hi, check this out Query Params
I am having trouble with the Route path <Route path="customers/:id" render={(props) => <CusDataForm {...props}/>}/> in the code below:
import CusDataCtrl from './cusdata/CusDataCtrl'
import CusDataForm from './cusdata/CusDataForm'
class App extends Component {
render() {
return (
<BrowserRouter>
<Switch>
<Route exact path="/customers" component={CusDataCtrl} />
<Route path="customers/:id" render={(props) => <CusDataForm {...props}/>}/>
</Switch>
</BrowserRouter>
);
}
}
export default App;
if I use <Route exact path="/customers/:id" component={CusDataForm} /> the component does render correctly; however, I need to pass some props down to this component.
My calling component is defined like so:
class CusDataGrid extends Component {
constructor(props) {
super(props)
this.state = {data: []}
}
componentDidMount() {
let me = this;
dbFetch("customers",data => me.setState({data:data}));
}
callEdit = e => {
let recid = e.target.getAttribute("data")
this.props.history.push("/customers/"+recid);
}
render() {
const rows = this.state.data.map((row, ndx) => {
return (
<div key={ndx}><button data={row.recordid} className="waves-effect waves-light btn-small" onClick={this.callEdit}>Edit</button></div>
);
});
return (
<div id="cusdata"><div className="data-scrollable">{rows}</div></div>
);
}
};
export default CusDataGrid;
and my target component is:
class CusDataForm extends Component{
componentDidMount = () =>{
this.setState({id: this.props.id ? this.props.id : ""});
}
render(){
return(<div>HELLO</div>)
}
}
export default CusDataForm;
Please let me know what I am doing incorrectly. Thanks!
you can use hook useParams for it
<Switch>
<Route path="/:id" children={<Child />} />
</Switch>
function Child() {
// We can use the `useParams` hook here to access
// the dynamic pieces of the URL.
let { id } = useParams();
return (
<div>
<h3>ID: {id}</h3>
</div>
);
}
official documentation
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 am doing a simple react application and I have an App component which keeps track of the state and then renders it. At first the state it is an empty string. Afterwards when I access the /signin I click on a button that changes the state from "" to "Marc" and pass it via props to the Profile component who renders the name of the user on its page. The problem is that it does not change the state and it is always "". I tried to debug and the state is always "" but the method setState is actually called. So i do not know why. Can anyone help me? Thanks in advance and I enclose the code.
APP:
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
session: ""
};
this.updateUser = this.updateUser.bind(this);
}
updateUser() {
this.setState({
session: "Marc"
});
}
render() {
return(
<BrowserRouter>
<Switch>
<Route path exact='/' component={Home}/>
<Route path='/profile' render={(props) => (
<Profile session={this.state.session} />
)}/>
<Route path='/signin' render={(props) => (
<SignIn onClick={this.updateUser} />
)}/>
</Switch>
</BrowserRouter>
);
}
}
SIGNIN:
export default class SignIn extends React.Component{
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
responseGoogle (googleUser) {
const mail = googleUser.profileObj.email;
const familyName = googleUser.profileObj.familyName;
const name = googleUser.profileObj.name;
//this.changeName(mail);
alert("Mail: " + mail + "\n" + "Nom i Cognoms: " + name + "\nSuccessfully Logged In");
}
handleClick() {
this.props.onClick();
}
render () {
return (
<div>
<GoogleLogin
clientId="CLIENTID"
onSuccess={this.responseGoogle}
onFailure={this.responseGoogle}
buttonText="Google"/>
<button onClick={this.handleClick}>Instant User</button>
</div>
);
}
}
PROFILE:
export default class Profile extends React.Component {
constructor(props) {
super(props)
}
render() {
return(
<h1>I am {this.props.session} User</h1>
);
}
}
In your case when at the SignIn component, onClicking the button will update the State correctly, but when you try to visit another page say Profile by manually entering the URL in browser, your state change will be lost and the state will be reinitialized as you session has changed.
You should instead try to navigate Programatically , for which you could refer the following answer on StackOverflow:
Programatically Routing based on a condition with react-router
In short In SignIn component you will have
class SignIn extends React.Component {
...
handleClick() {
this.props.onClick();
this.props.history.push('/profile');
}
...
export default withRouter(SignIn);
The above is what I will recommend you to do, or else for testing you can have a Link component and navigate using that
render() {
return(
<BrowserRouter>
<div>
<Link to="/profile">Profile</Link>
<Switch>
<Route path exact='/' component={Home}/>
<Route path='/profile' render={(props) => (
<Profile session={this.state.session} />
)}/>
<Route path='/signin' render={(props) => (
<SignIn onClick={this.updateUser} />
)}/>
</Switch>
</div>
</BrowserRouter>
);
}
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.