Unable to console.log props using Link - javascript

I am trying to make a single web application. Basically, I am trying to use the ReactRouter to display what is passed as a Route Parameter. However, I am unable to do that. To check if somethings wrong, I decided to console.log out this.props.match, still nothing shows up. Could someone explain what the problem is? And a possible get around?
My code is-
import React from 'react';
export default class Post extends React.Component {
state = {
id: null
}
componentDidMount(props) {
console.log(this.props.match);
}
render = () => {
return (<div>Hello WOrld</div>)
}
}
The App.js file:
import React, { Fragment, Component } from 'react';
import Navbar from './components/Navbar';
import Home from './components/Home';
import Contact from './components/Contact';
import About from './components/About'
import Post from './components/Post';
import { BrowserRouter, Route } from 'react-router-dom';
class App extends Component {
render = () => {
return (
<BrowserRouter>
<div className="App">
<Navbar />
<Route exact path="/" component={Home} />
<Route path="/contact" component={Contact} />
<Route path="/about" component={About} />
<Route path="/:post-id" component = {Post} />
</div>
</BrowserRouter>
);
}
}
export default App;

I just ran your code on my end, it looks like the problem is using /:post-id. I changed that to /:pid and it worked. I got the below object when I console log this.props.match
{
"path":"/:pid",
"url":"/1",
"isExact":true,
"params":
{
"pid":"1"
}
}
I hope this helps.

You have to load the component with router
try this
import { withRouter } from 'react-router-dom';
class Post extends React.Component {
state = {
id: null
}
componentDidMount(props) {
console.log(this.props.match);
}
render = () => {
return (<div>Hello WOrld</div>)
}
}
export default withRouter(Post);

Related

React Router returns blank page with correct pathing

I'm new to react. I'm following a tutorial, and my code is exactly the same as the tutorial, but the result isn't. Basically, my page routes are returning a blank page. There's no error in the console, so I'm not sure what I'm doing wrong. Here's my code
Homepage.js
import React, { Component } from "react";
import Login from "./Login";
import CreateUser from "./CreateUser";
import {
BrowserRouter as Router,
Switch,
Route,
Link,
Redirect,
} from "react-router-dom";
export default class HomePage extends Component {
constructor(props) {
super(props);
}
render() {
return (
<Router>
<Switch>
<Route exact path="/">
<p>This is the homepage</p>
</Route>
<Route path="/login" component={Login} />
<Route path="/createuser" component={CreateUser} />
</Switch>
</Router>
);
}
}
Login.js Component
import React, { Component } from "react";
export default class Login extends Component {
constructor(props) {
super(props);
}
render() {
return <p>This is the Login Page</p>;
}
}
CreateUser.js Component
import React, { Component } from "react";
export default class CreateUser extends Component {
constructor(props) {
super(props);
}
render() {
return <p>This is the Create User Page</p>;
}
}
App.js
import React, { Component } from "React";
import { render } from "react-dom";
import HomePage from "./HomePage";
export default class App extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<HomePage />
</div>
);
}
}
const appDiv = document.getElementById("app"); // get 'app' div
render(<App />, appDiv); // place App component into app div
I've tried changing the import "react" code in line 1 to import 'react' among other things.
Any ideas? Thanks!
Try changing the paths to "/login" and "/createuser" in Homepage.js
I am using Django on the backend of the React project I'm working on. The routes were not connected to the url.py file for the url configuration for my Django app.

React navigation - cannot read property 'push' of undefined

I have a create profile page and an auth page (where one enters a code sent by text). I'd like to navigate to the auth page, when a profile is created.
I have a component for the create profile page and one for the auth page.
Based on the example here.
Relevant code:
// CreateProfileComponent.js
import React from 'react';
..
import { withRouter } from "react-router";
class CreateProfile extends React.Component {
constructor(props) {
super(props);
}
handleCreateProfile(e) {
e.preventDefault();
if (condition) {
createProfile(...);
this.props.history.push('/auth');
} else {
// re-render
}
}
render() {
return (
// data-testid="create-profile" - workaround (https://kula.blog/posts/test_on_submit_in_react_testing_library/) for
// https://github.com/jsdom/jsdom/issues/1937
<form onSubmit={this.handleCreateProfile.bind(this)} data-testid="create-profile">
...
</form>
);
}
}
export default withRouter(CreateProfile);
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import CreateProfile from './CreateProfileComponent';
import { TokenEntry } from './TokenEntryComponent';
ReactDOM.render(
<Router>
<ProtectedRoute exact path="/" component={ActivityList} />
<Route path="/login" component={CreateProfile.WrappedComponent} />
<Route path="/auth" component={TokenEntry} />
</Router>,
document.getElementById('root')
);
//createprofilecomponent.test.js
import React from 'react';
import {
LocationProvider,
createMemorySource,
createHistory
} from '#reach/router';
import { render, screen, fireEvent } from '#testing-library/react';
import CreateProfile from '../CreateProfileComponent';
const source = createMemorySource('/login');
const history = createHistory(source);
let displayName = null;
let phoneNumber = null;
let legalAgreement = null;
global.window = { location: { pathname: null } };
function Wrapper({children}) {
return <LocationProvider history={history}>{children}</LocationProvider>;
}
beforeEach(() => {
render(
<CreateProfile.WrappedComponent location={'/'} />,
{ wrapper: Wrapper }
);
});
it("navigates to /auth when good data entered", () => {
// setup
fireEvent.submit(screen.getByTestId('create-profile'));
expect(global.window.location.pathname).toEqual('/auth');
});
I'm getting
TypeError: Cannot read property 'push' of undefined
during tests and in Chrome.
What am I missing?
Use the react-router-dom
import { withRouter } from "react-router-dom";
Changed
export default withRouter(CreateProfile);
To
export const CreateProfileWithRouter = withRouter(CreateProfile);
Changed
<Route path="/login" component={CreateProfileWithRouter.WrappedComponent} />
To
<Route path="/login" component={CreateProfileWithRouter} />
Pull request created to include an example in withRouter's documentation.
Example gist

Child component is not updating from parent state change

I'm trying to update my child component's photos from the parent components state. For all the other routes, the appropriate function was already invoked once the app was mounted. The component that renders cats, dogs, or computers is PhotoList.js
But now, I want to be able to enter a parameter after search (ex. /search/:id) and run a function called getImages in my Container.js to search for any type of picture from the Flickr API.
I tried using componentDidMount and invoking the getImages function with the match parameter inside of it but it doesn't seem to change the data props that's put into it. Does anyone have any suggestions as to how I can make this?
Here is Container.js
import React, {Component} from 'react';
import Photo from './Photo';
class Container extends Component {
componentDidMount() {
this.props.getImages(this.props.match.id)
}
render() {
return (
<div className="photo-container">
<h2>Results</h2>
<ul>
{this.props.data.map((photo,index)=>
<Photo
farm={photo.farm}
server={photo.server}
id={photo.id}
secret={photo.secret}
key={index}
/>
)}
</ul>
</div>
);
}
}
export default Container
Here is PhotoList.js
import React, {Component} from 'react';
import Photo from './Photo';
import NoResults from './NoResults';
class PhotoList extends Component {
render() {
return (
<div className="photo-container">
<h2>Results</h2>
<ul>
{this.props.data.map((photo,index)=>
<Photo
farm={photo.farm}
server={photo.server}
id={photo.id}
secret={photo.secret}
key={index}
/>
)}
</ul>
</div>
);
}
}
export default PhotoList;
Here is App.js
import React, {Component} from 'react';
import {
BrowserRouter,
Route,
Switch,
Redirect
} from 'react-router-dom';
import Search from './Search';
import Nav from './Nav';
import '../index.css';
import axios from 'axios';
import apiKey from './Config';
import NotFound from './NotFound';
import PhotoList from './PhotoList';
import NoResults from './NoResults';
import Container from './Container';
class App extends Component {
state= {
cats: [],
dogs: [],
computers: [],
searchResult: [],
loading: true
}
componentDidMount() {
this.getCats()
this.getDogs()
this.getComputers()
}
getCats=(query='cats')=> {
axios.get(`https://www.flickr.com/services/rest/?method=flickr.photos.search&api_key=${apiKey}&tags=${query}&per_page=24&page=1&format=json&nojsoncallback=1`)
.then(res=> {
const cats=res.data.photos.photo
this.setState({cats})
}).catch((error)=> {
console.log("There was an error parsing your data", error);
})
}
getDogs=(query='dogs')=> {
axios.get(`https://www.flickr.com/services/rest/?method=flickr.photos.search&api_key=${apiKey}&tags=${query}&per_page=24&page=1&format=json&nojsoncallback=1`)
.then(res=> {
const dogs=res.data.photos.photo
this.setState({dogs})
}).catch((error)=> {
console.log("There was an error parsing your data", error);
})
}
getComputers=(query='computers')=> {
axios.get(`https://www.flickr.com/services/rest/?method=flickr.photos.search&api_key=${apiKey}&tags=${query}&per_page=24&page=1&format=json&nojsoncallback=1`)
.then(res=> {
const computers=res.data.photos.photo
this.setState({computers});
}).catch((error)=> {
console.log("There was an error parsing your data", error);
})
}
getImages=(query)=> {
axios.get(`https://www.flickr.com/services/rest/?method=flickr.photos.search&api_key=${apiKey}&tags=${query}&per_page=24&page=1&format=json&nojsoncallback=1`)
.then (res=> {
const searchResult=res.data.photos.photo
this.setState({searchResult});
}).catch((error)=> {
console.log("There was an error parsing your data", error);
})
}
render() {
return (
<div className="container">
<Search getImages={this.getImages}/>
<Nav />
<Switch>
<Route exact path="/" render={()=> <Redirect to={'/cats'} />} />
<Route path='/cats' render={()=> <PhotoList data={this.state.cats}/>} />
<Route path='/dogs' render={()=> <PhotoList data={this.state.dogs} />} />
<Route exact path='/computers' render={()=> <PhotoList data={this.state.computers} />} />
<Route path='/search/:id' render={(props)=> <Container {...props} getImages={this.getImages} data={this.state.searchResult} />} />
<Route component={NotFound}/>
</Switch>
</div>
)
}
}
export default App;
Assuming your are using react-router-dom 4 and above.
Try
import React, { Component } from "react";
import { withRouter } from "react-router-dom"; //<-- import this
import Photo from "./Photo";
class Container extends Component {
componentDidMount() {
// Your this.props.match.id is likely undefined
this.props.getImages(this.props.match.params.id); // <-- Change here
}
...
}
export default withRouter(Container); // <-- Change this

Cannot read property 'push' in react

I'm trying to get a component that will appear after a second.
The component itself simply has only H1.
I use a router so the most correct solution would seem to me to use the history.push but it does not work for me, what am I doing wrong?
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import {withRouter} from 'react-router-dom'
import './App.css';
import Hello from './comp/Hello';
class App extends Component {
render() {
return (
<Router>
<div className="App">
</div>
<Route path="/hello" component={Hello} />
</Router>
);
}
componentWillMount() {
this.hello()
}
hello(){
setTimeout(() => {
this.props.history.push('/hello')
}, 1000);
}
}
export default App;
===========================the Component========================
import React, { Component } from 'react';
class App extends Component {
render() {
return (
<div className="App">
<h1>hi</h1>
</div>
);
}
}
export default App;
i think you need to wrap you component with withRouter hook .
try like below,
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import {withRouter} from 'react-router-dom'
import './App.css';
import Hello from './comp/Hello';
class App extends Component {
render() {
return (
<Router>
<div className="App">
</div>
<Route path="/hello" component={Hello} />
</Router>
);
}
componentWillMount() {
this.hello()
}
hello(){
setTimeout(() => {
this.props.history.push('/hello')
}, 1000);
}
}
export default withRouter(App);
It is hard to see exactly what is going on, usually only child components suffer from these kinds of errors in my experience, because the props.history is not being passed on. The Apps component should in most cases be the main component though.
Regardless, in the meantime I suggest you try this approach:
import { BrowserRouter as Router, Route, Link, Redirect } from "react-router-dom";
...
hello(){
setTimeout(() => {
return <Redirect to={{
pathname: "/hello",
state: {
optionalStateToPass,
},
}} />;
}, 1000);
}
...
For a component to receive the history prop, you need 2 things:
Router must be at the top level, above all calls to Route, Link, and withRouter
The component that needs the prop history must be rendered by a Route, e.g. <Route component={ComponentThatNeedsHistoryProp} ...> OR wrap it with withRouter.
In your case, it seems you cannot rely on the route props to be passed, so we need to use withRouter.
It should look like this (imports not shown):
// App.js
class App = () => (
<div className="App">
<Router>
<Hello />
</Router>
</div>
)
// Hello.js
class Hello extends Component {
render() {
return <h1>hi</h1>
}
componentWillMount() {
this.hello()
}
hello(){
setTimeout(() => {
this.props.history.push('/hello')
}, 1000);
}
}
export default withRouter(Hello);

React-router-dom and Redux not rerendered the component

EDIT : I found the solution, I forget switch component in my routes.js
I have created a route like that : /post/:id
my routes.js look like :
import React, { Component } from "react";
import { BrowserRouter, Route } from "react-router-dom";
import Posts from "./components/Posts";
import Post from "./components/Post";
class Routes extends Component {
render() {
return (
<div>
<BrowserRouter>
<div>
<Route exact path="/" component={Posts} />
<Route path="/post/:id" component={Post} />
</div>
</BrowserRouter>
</div>
);
}
}
export default Routes;
At my /route I listed all my posts, and when I click on one of them I update the url http://localhost:3000/post/1 for example.
PS : I tried to use withRouter function as it says in the official document of react-router, but this case not work in my case.
The file in question is post.js it look like :
import React, { Component } from "react";
import { active_post } from "../actions/index";
import { bindActionCreators } from "redux";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
class Post extends Component {
componentWillMount() {
this.props.active_post(this.props.match.params.id);
}
render() {
console.log(this.props.post);
return (
<div>
<h1>Detail d'un post</h1>
<p>{this.props.match.params.id}</p>
</div>
);
}
}
function mapStateToProps(state) {
return {
post: state.activePost
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({ active_post }, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(Post);
So for example, if I enter manually in the URL bar http://localhost:3000/post/3 for example I have the component and the console.log() with the post when I need.
So please if you have a solution for this case I take this.
Thanks you :)
You should try adding a Switch from react-router-dom around your routes.
<BrowserRouter>
<div>
<Switch>
<Route exact path="/" component={Posts} />
<Route path="/post/:id" component={Post} />
</Switch>
</div>
</BrowserRouter>
Don't forget to include the Switch module from react-router-dom in your component.
import { Route, Switch } from 'react-router-dom';

Categories

Resources