I have 2 class component PhoneDirectory.js and App.js
class PhoneDirectory extends Component {
render() {
return (
<BrowserRouter>
<Routes>
<Route exact path="/" element={<App />} render={(props) => <App {...props} name="test" />} />
</Routes>
</BrowserRouter>
)
};
}
export default PhoneDirectory;
The other Class Component
class App extends Component {
render() {
console.log("value:", this.props.name);
return (
);
}
}
export default App;
Here in App.js I am getting undefined in console logs.
In react-router-dom#6 there are no longer component and render and children function props, they were replaced by a single element prop taking a ReactNode, a.k.a. JSX. You can pass additional props.
Example:
<Route path="/" element={<App name="test" />} />
...
class App extends Component{
componentDidMount() {
console.log("value:", this.props.name);
}
render() {
return ....;
}
}
export default App;
Related
I am defining the routes in react
Global ones in the app-routes.js file and other in their respective components.
app.js
render() {
return (
<div className="App-wrap">
<AppRoutes/>
</div>
); }
app-route.js
export class AppRoutes extends React.Component {
render() {
return (
<Router>
<Switch>
<Route path="/" component={LayoutComponent} />
</Switch>
</Router>
);
}
}
layout-component.js
I have placed my header here for navigation
export class LayoutComponent extends React.Component {
render() {
return (
<LayoutWrap>
<HeaderComponent> </HeaderComponent>
<LayoutRoutes />
</LayoutWrap>
);
}
}
layout.routing.js
export class LayoutRoutes extends React.Component {
render() {
return (
<Switch>
<Route path="/" exact >
<Redirect to="/users"/>
</Route>
<Route path="/users" name="Users" component={UserComponent} />
<Route path="/permissions" name="Permissions" component={PermissionComponent} />
</Switch>
);
}
}
Now the issue is, when i am defining my child routes, my child routes are dependent on parent
i.e. i have to write parent's previous url in child.
If i change my app-routes.js path from "" to layout my routing will not work.
<Route path="/layout" component={LayoutComponent} />
How to solve the issue?
When you are defining your child Routes, you need to prefix the parent route path before it for these to work. For this you can make use of match.path from props like
export class LayoutRoutes extends React.Component {
render() {
const { match } = this.props;
return (
<Switch>
<Route path={match.path} exact render ={(props) => <Redirect to="/users"/>} />
<Route path=`${match.path}/users` name="Users" component={UserComponent} />
<Route path=`${match.path}/permissions` name="Permissions" component={PermissionComponent} />
</Switch>
);
}
}
I'm new to react and redux world. I have a question regarding react router. Following is my App component.
class App extends React.PureComponent {
render() {
return (
<div>
<Switch>
<Route exact path="/" component={HomePage} />
<Route exact path="/callback" component={CallbackPage} />
<Route exact path="/list" component={List} />
<Route component={NotFoundPage} />
</Switch>
</div>
);
}
}
export default App;
My list class looks like this:
export class List extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
isOpen: false,
};
this.depositHandleToggle = this.depositHandleToggle.bind(this);
}
depositHandleToggle = () => {
this.props.dispatch(push(`${this.props.match.url}/deposit`));
}
render() {
const { match } = this.props;
return (
<div>
<Route path={`${match.url}/deposit`} component={Modal} />
<button onClick={this.depositHandleToggle}>Open Modal</button>
</div>
);
}
}
export default List;
So my question is: when i click the button in List container, why my router can't find this url 'localhost:xxx/list/deposit'? it renders the App component but it never goes back to List component. Is it possible to have the custom routes inside my list container? Am i doing something wrong? Please someone help me with this.
I hope you understand my question. Thanks in advance.
ANSWER:
I found the answer, the issue was in my App component list route. I was having the 'exact' keyword, that's why route inside my list component was not working. Following way is the correct way.
<Route path="/list" component={List} />
I hope this will help someone.
import { Link } from 'react-router-dom';
class App extends React.PureComponent {
render() {
return (
<div>
<Switch>
<Route exact path="/" component={HomePage} />
<Route exact path="/callback" component={CallbackPage} />
<Route exact path="/list" component={List} />
<Route exact path="/list/deposit" component={Modal} />
<Route component={NotFoundPage} />
</Switch>
</div>
);
}
}
export default App;
export class List extends React.PureComponent {
constructor(props) {
super(props);
}
render() {
const { match } = this.props;
return (
<div>
<Link to={'/deposit'}>Open Modal</Link>
);
}
}
export default List;
in that component you should handle modal open close.
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 want to pass props and invoke actions in my Layout component. When I try to do it with the following code, only the initial state is passed. The changes in the redux store are not reflected.
This is the code to initiate the app.
ReactDOM.render(
<AppContainer>
<Provider store={ store }>
<ConnectedRouter history={ history } >
<Layout prop={store.getState()}>
<Route exact path='/' component={ Dashboard } />
<Route path='/workorder' component={ WorkOrder } />
<Route path='/programs' component={ Programs } />
<Route path='/departments' component={ Departments } />
<Route path='/users' component={ Users } />
<Route path='/fetchdata/:startDateIndex?' component={ FetchData } />
</Layout>
</ConnectedRouter>
</Provider>
</AppContainer>,
document.getElementById('react-app')
);
This is the code of the layout page.
interface LayoutProps{
prop: any;
}
export class Layout extends React.Component<LayoutProps, {}> {
public render() {
console.log(this.props);
return <div>
<Header/>
<div id="wrapper">
<NavMenu/>
{ this.props.children }
</div>
</div>;
}
}
My console log only prints the initial state all the time. I don't know why it is not getting updated. I have this problem only for layout. All the other components defined in the routes are connected using 'connect' and works properly.
Edit: This is the updated code:
ReactDOM.render(
<AppContainer>
<Provider store={ store }>
<ConnectedRouter history={ history } >
<Layout>
<Route exact path='/' component={ Dashboard } />
<Route path='/workorder' component={ WorkOrder } />
<Route path='/programs' component={ Programs } />
<Route path='/departments' component={ Departments } />
<Route path='/users' component={ Users } />
<Route path='/fetchdata/:startDateIndex?' component={ FetchData } />
</Layout>
</ConnectedRouter>
</Provider>
</AppContainer>,
document.getElementById('react-app')
);
This is the code in Layout:
export class Layout extends React.Component<any, {}> {
public render() {
console.log(this.props);
return <div>
<Header/>
<div id="wrapper">
<NavMenu/>
{ this.props.children }
</div>
</div>;
}
}
export default connect(
(state: ApplicationState) => state.users, // Selects which state properties are merged into the component's props
UsersStore.actionCreators.getCurrentUser // Selects which action creators are merged into the component's props
)(Layout) as typeof Layout;
But only props.children are available inside the Layout component. All the other props are undefined even though I pass state.users, UsersStore.actionCreators.getCurrentUser. Basically it is not taking anything from redux store (Even after any number of re-renders).
You need to be using react-redux's connect enchancer.
import { connect } from 'react-redux'
import { updateSomething } from 'actions'
class LayoutComponent extends React.Component {
render() {
return (
<div onClick={this.props.updateSomething}>
something: {this.props.something}
</div>
)
}
}
export Layout = connect((state) => {
return { something: state.something }
}, { updateSomething })(LayoutComponent)
edit: see here for more information
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?