problem function is not being defined in react class based component - javascript

I created a state and assigned a function to change the state using setState() and passed the function to a component but the function is not declared.
News.js:34 Uncaught (in promise) TypeError: this.setProgress is not a function
at News.updateNews (News.js:34:1)
at News.componentDidMount (News.js:50:1)
at commitLayoutEffectOnFiber (react-dom.development.js:23305:1)
at commitLayoutMountEffects_complete (react-dom.development.js:24688:1)
at commitLayoutEffects_begin (react-dom.development.js:24674:1)
at commitLayoutEffects (react-dom.development.js:24612:1)
at commitRootImpl (react-dom.development.js:26823:1)
at commitRoot (react-dom.development.js:26682:1)
at finishConcurrentRender (react-dom.development.js:25981:1)
at performConcurrentWorkOnRoot (react-dom.development.js:25809:1)
app.js
import './App.css';
import React, { Component } from 'react'
import NavBar from './components/NavBar';
import News from './components/News';
import { BrowserRouter as Router,Routes,Route } from 'react-router-dom';
import LoadingBar from 'react-top-loading-bar'
export default class App extends Component {
state = {
progress:0
}
setProgress=(progress)=>{
this.setState({progress:progress});
}
<Router>
<Routes>
<Route path="/" element={<News progress={this.setProgress} key="General" pageSize={this.pageSize} country={'in'} category={'General'}/>} exact/>
<Routes/>
<Router/>
News.js
import React, { Component } from "react";
import NewsItem from "./NewsItem";
import Spinner from "./Spinner";
import PropTypes from "prop-types";
import InfiniteScroll from "react-infinite-scroll-component";
export class News extends Component {
async updateNews() {
this.setProgress(10);
const url = `https://newsapi.org/v2/top-headlines?country=${this.props.country}&category=${this.props.category}&apiKey=05850f6a9b5842cdb656e413b672544a&page=${this.state.page}&pageSize=${this.props.pageSize}`;
this.setState({ loading: true });
let data = await fetch(url);
this.props.setProgress(30);
let parsedData = await data.json();
this.props.setProgress(70);
this.setState({
articles: this.state.articles.concat(parsedData.articles),
totalResults: parsedData.totalResults,
loading:false
});
this.props.setProgress(100);
}
}

You should change the line
<Route path="/" element={<News progress={this.setProgress} key="General" pageSize={this.pageSize} country={'in'} category={'General'}/>} exact/>
to
<Route path="/" element={<News setProgress={this.setProgress} key="General" pageSize={this.pageSize} country={'in'} category={'General'}/>} exact/>
Also, in your News.js file, you should change the line
this.setProgress(10);
to
this.props.setProgress(10);
This way, you are passing the setProgress function correctly and also invoking it correctly in News.js file.
Also, you should use class properties syntax to define your state, instead of using the constructor, like this:
state = {
progress:0
}
Hope this helps!

Related

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

Unable to console.log props using Link

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);

Warning: Failed prop type: Invalid prop 'component' supplied to 'Route' - react-router-dom

I want to solve this warning. I get this warning once I added react-router-dom to App.js.
(The application itself is working fine with this warning.)
Warning message:
index.js:1 Warning: Failed prop type: Invalid prop 'component' supplied to 'Route': the prop is not a valid React component
in Route (at App.js:34)
in App (at src/index.js:9)
in Router (created by HashRouter)
in HashRouter (at src/index.js:8)
I'm just passing down the state down to the child component form App.js
App.js
import React, { Component } from 'react'
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'
import './App.css'
import MasterPassword from './MasterPassword'
import EncryptForm from './EncryptForm'
import NotFound from './NotFound'
class App extends Component {
constructor(props) {
super(props)
this.state = {
masterPassword: null
}
}
getMasterPassword = userPassword => {
this.setState({
masterPassword: userPassword
})
}
render() {
return (
<Router>
{!this.state.masterPassword
? <MasterPassword
path='/ask-password'
masterPassword={this.state.masterPassword}
onStorePassword={this.getMasterPassword}
/>
: <div className="App">
<Switch>
<Route exact path='/' render={() => <EncryptForm masterPassword={this.state.masterPassword} />} />
<Route component={<NotFound />} />
</Switch>
</div>}
</Router>
)
}
}
export default App
index.js
import React from 'react'
import ReactDOM from 'react-dom'
import { HashRouter } from 'react-router-dom'
import './index.css'
import App from './components/App'
import * as serviceWorker from './serviceWorker'
ReactDOM.render(<HashRouter>
<App />
</HashRouter>, document.getElementById('root'))
serviceWorker.unregister()
Thank you!
Change this <Route component={<NotFound />} /> to this: <Route component={NotFound} />
This is pretty standard behavior for libraries like this. They want to render the component like this: <component /> rather than like this: {component}.
#Asher's answer should work, but if you have props that you'd like to pass in, then you can pass the component in an inline function that creates the React element:
<Switch><Route component={() => <NotFound message={notFoundMessage} />}/></Switch>
Resource: https://ui.dev/react-router-v4-pass-props-to-components/

Warning: Failed context type: The context `store.isRequired` is marked as required in `Routing`, but its value is `undefined`

I'm having an issue with react-redux Provider:
I moved our router out of our index.js to a routing.js file. I used a Provider to give my Routing component knowledge of the store but I'm getting a strange warning before the execution reaches the render method :
Warning: Failed context type: The context `store.isRequired` is marked as required in `Routing`, but its value is `undefined`.
This happens even if I get rid of the .isRequired in Routing.contextTypes. Moreover if I put a debugger statement at the beginning of the render function, it appears that this.contextisn't undefined and my app is working like a charm. I'm wondering if I did something wrong or if it could possibly be a bug of react-redux Provider or something.
Here is my code:
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { setLanguage } from 'redux-i18n';
import I18n from 'redux-i18n/immutable';
import configureStore from './store/configure_store';
import { Routing } from './routing';
import translations from './translations';
import '../scss/index.scss';
const store = configureStore();
store.dispatch(setLanguage(navigator.language));
ReactDOM.render(
<Provider store={ store }>
<I18n translations={ translations }>
<Routing />
</I18n>
</Provider>,
document.getElementById("root")
);
routing.js (simplified for reading purpose)
import React from 'react';
import { Route, IndexRedirect, IndexRoute, Router, browserHistory } from 'react-router';
import AppContainer from './components/App/App';
import Base from './components/Root/Base';
import BaseInProject from './components/App/BaseInProject';
import { ProjectListContainer } from './components/App/Projects/ProjectsList';
export class Routing extends React.Component {
render() {
const { store } = this.context;
const beforeAppRouteEnter = (nextState, replace, callback) => {
// This function needs to store.dispatch some stuff
};
// Some other router functions
const routes = (
<Route path='/' component={ Base }>
<Route component={ AppContainer } onEnter={ beforeAppRouteEnter }>
<IndexRoute component={ ProjectListContainer } />
// Some other routes
<IndexRedirect to='media' />
</Route>
</Route>
</Route>
);
return (
<Router history={ browserHistory }>{ routes }</Router>
);
}
}
Routing.contextTypes = {
store: React.PropTypes.shape(React.PropTypes.any)
};
Thanks!

React-router: TypeError: Cannot set property 'props' of undefined

I am trying to set up routing in Meteor using react-router package and have encountered the following TypeError:
Link to image: https://postimg.org/image/v0twphnc7/
The code in I use in main.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, IndexRoute, browserHistory } from 'react-router';
// Importing components
import App from './components/app';
import Portfolio from './components/portfolio/portfolio';
//Creating a route
const routes = (
<Router history={browserHistory}>
<Route path='/' component={App}>
<Router path='portfolio' component={Portfolio} />
</Route>
</Router>
);
// Loading routes
Meteor.startup(() => {
ReactDOM.render(routes, document.querySelector('.universe'));
});
The problem that I've managed to identify is that when I define portfolio as a Simple Component it works.
const Portfolio = () => {
return (
<div className='red'>Portfolio page</div>
);
}
But when I extend it from the Component is where the error comes in:
class Portfolio extends Component () {
render() {
return (
<div>Portfolio page</div>
);
}
}
Can you please explain the possible difference between "normal" and class component and why the following error appears.
Assuming you are importing Component as a React.Component correctly, try removing the parenthesis after Component.
Should be:
class Portfolio extends Component {
instead of:
class Portfolio extends Component () {
If not, replace Componentwith React.Component.

Categories

Resources