'TypeError: this is undefined' occurs when using members of a class from a functional component - node.js

I am trying to pass data to a ReactJS component using NodeJS by making a simple NodeJS API hosted in a separate localhost (:9000). But I'm getting an error.
TypeError: this is undefined
My belief is that this error occurred due to using 'this' inside the functional component. But I cannot find a way to resolve this problem.
The code which has the error:
import React from 'react';
import ReactDOM from 'react-dom';
class News extends React.Component{
constructor (props){
super(props);
this.state={apiResponse:""};
}
callAPI(){
fetch("http://localhost:9000/testAPI")
.then(res => res.text ())
.then(res => this.setState({apiResponse: res}));
}
componentWillMount(){
this.callAPI();
}
}
function Newsexport() {
return (
<div class="container1">
<h1>IT WORKS YO!</h1>
<p>{this.state.apiResponse}</p>
</div>
)
};
export default Newsexport;
The code of the simple API hosted with NodeJS (/api/routes/testAPI.js)
var express = require("express");
var router=express.Router();
router.get("/", function(req,res,next){
res.send("API is working");
});
module.exports=router;

You are using this in a functional component which is wrong. Also you are setting state in one component and expecting the value in another component. Instead combine the two components like below -
class News extends React.Component{
constructor (props){
super(props);
this.state={apiResponse:""};
}
callAPI = () => {
fetch("http://localhost:9000/testAPI")
.then(res => res.text ())
.then(res => this.setState({apiResponse: res}));
}
componentWillMount(){
this.callAPI();
}
render() {
return (
<div class="container1">
<h1>IT WORKS YO!</h1>
<p>{this.state.apiResponse}</p>
</div>
)
}
}
export default News;
Let me know if this helps.

Related

Nodejs not sending data in Reactjs functional component

When you call it in http://localhost:9000/testApi, it works fine.
testAPI.js
const express = require('express');
var router = express.Router();
router.get("/",function(req,res){
res.send("API is working fine");
});
module.exports = router;
But Calling in ReactJS functional component leads to nothing
import React, {useState, useEffect} from 'react';
import TopicCard from './TopicCard.js'
import './HomePage.css'
function HomePage() {
const [apiResponse,setApiResponse] = useState('Loading..')
const url = "http://localhost:9000/"
useEffect(() => {
fetch(url).then(res => setApiResponse(res.data))
}, [])
return (
<>
<h1>Choose a topic to learn {apiResponse}</h1>
</>
);
Console.log gives this
PromiseĀ {}[[Prototype]]: Promise [[PromiseState]]: "rejected"
[[PromiseResult]]: SyntaxError: Unexpected token A in JSON at position
0
While the Class Component is working perfectly fine
import React, {Component} from 'react'
class Test extends Component {
constructor(props) {
super(props);
this.state = { apiResponse: "" };
}
callAPI() {
fetch("http://localhost:9000/testAPI")
.then(res => res.text())
.then(res => this.setState({ apiResponse: res }));
}
componentWillMount() {
this.callAPI();
}
render()
{
return (
<div>
<p className="App-intro">;{this.state.apiResponse}</p>
</div>
);
}
}
export default Test
No differences are between functional and class-based components.
The Problem
You forgot to parse your response as a text in the fetch method.
The Solution
parse your data as a text and then store it on your state variable
useEffect(() => {
fetch(URL)
.then(res => res.text())
.then(res => setApiResponse(res))
.catch(err => console.warn(err))
}, [])
Note: don't forget to use catch method for your asynchronous fetch API.
Explanation
When your data (API call response) is in standard JSON format, you need to parse them with .json() method, and usually, a data property holds the whole response, but in your case (with a text as a response) it's not useful.
Are you confusing routes / end points with file names? testAPI.js is your file name. It's not your endpoint.
You call:
const url = "http://localhost:9000/testAPI"
useEffect(() => {
fetch(url).then(res => setApiResponse(res.data))
}, [])
But your endpoint is - a forward slash '/' i.e. the root (not ROUTE) :
router.get("/",function(req,res){
res.send("API is working fine");
});
Try changing to this:
const url = "http://localhost:9000/"
useEffect(() => {
fetch(url).then(res => setApiResponse(res.data))
}, [])
If you want to fetch const url = "http://localhost:9000/testAPI" from react then change the endpoint to:
const url = "http://localhost:9000/testAPI" else server won't know of it.

the results of my api (back end part) is not displayed in the front end part using reactjs

I am a beginner in nodejs and reactjs and I am developing a simple application. I am now in the front part, I installed all the necessary packages and modules. I launched my front part but nothing is displayed here is a screenshot of the result obtained. thank you in advance
And here a part of my code in reactjs
import React from 'react';
import {connect} from 'react-redux';
import {fetchVideos} from '../actions/videoActions';
var listVideos
class videos extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() { this.props.fetchVideos(); }
render() {
if (this.props.data) {
listVideos = this.props.videos.map(video =>
<li key={video._id}>
{video.titre}
</li>
);
}
return (
<div>
<center><h1>All videos </h1></center>
{listVideos}
</div>
)
}
}
const mapStateToProps = (state, ownProps) => {
return {
clients : state.clients,
};
}
const mapDispatchToProps = (dispatch) => {
return {
fetchVideos :()=> dispatch(fetchVideos())
};
}
export default connect(mapStateToProps, mapDispatchToProps)(videos);
If you are using redux, probably you will need to map the videos in the mapStateToProps method
// ...
componentDidMount() { this.props.fetchVideos(); }
// ...
const mapStateToProps = (state, ownProps) => {
return {
clients : state.clients,
videos: state.videos // HERE
};
}
Note the state.videos param is got from the reducer.
In your component, you are trying to read videos from its props. However, as Luiz mentioned, your mapStateToProps is only mapping the clients state variable to your component. mapStateToProps is the logic that binds redux state with your component props. So, assuming that you have set the videos object on your state (via reducers) and adding the videos mapping on the mapStateToProps you should get said data on your component props.

pass state as props in component child in React

I get data from a local server, catch them with axios.get, and save them in my state. It's ok, but when i want to pass it as props in an component child, KABOOM! Doesn't work.
I'm looking for a solution, I think it's lyfecycle problem but i'm not sure.
App.js
import React, { Component } from 'react';
import './style/App.css';
import axios from 'axios'
import Table from './Components/Table'
class App extends Component {
state = {
tabData: [],
}
componentWillMount = () => {
this.getDataFromServer()
}
getDataFromServer = () => {
axios.get("http://localhost:8000")
.then((response) => {
const twentyObj = response.data.splice(-20);
this.setState({
tabData:twentyObj
})
console.log(this.state.tabData)
})
.catch(function (error) {
console.log(error);
})
}
render() {
return (
<div className="App">
<Table stateData={this.state.tabData}/>
</div>
);
}
}
export default App;
Developer Tools Browser say:
TypeError: _this.props is undefined
(for this.props.tabData.map in Table.js)
Table.js
import React from 'react';
import Cell from './Cell'
const Table = (props) => {
return(
<div>
{this.props.tabData.map( item =>
<Cell key={item.index}
time={item.timestamp}
nasdaq={item.stocks.NASDAQ}
cac40={item.stocks.CAC40}/>
)}
</div>
)
}
export default Table;
Table is functional component this has no value there and thats what the error message is telling you.
You should use props.tabData and not this.props.tabData
UPDATE:
Here you are passing it as stateData and not tabData Try props.stateData

React page shows the content and then shuts down after one second on node.js only

I am learning React, one of the examples I am practicing is getting data from Reddit api.
I have tried this code on "codesandbox" and it is working fine. But with node js it shows the first line "/r/reactjs" only and then turns off. It doesn't even show the data from Reddit inside the rendered page however when I checked React developer tools, the state has the array from Reddit api, so it is there already.
Here is my code
import React from "react";
import ReactDOM from "react-dom";
import axios from "axios";
import './App.css';
class Reddit extends React.Component {
state = {
posts: []
};
componentDidMount() {
axios.get(`https://www.reddit.com/r/reactjs.json`)
.then(res => {
const posts = res.data.data.children.map(obj => obj.data);
this.setState({ posts });
})
.catch(error => {
console.log(error.response)
});
}
render() {
return (
<div id='reddit_data'>
<h1>/r/reactjs</h1>
<ul>
{this.state.posts.map(post => {
return <li key={post.id}>{post.title}</li>;
})}
</ul>
</div>
);
}
}
ReactDOM.render(<Reddit />, document.getElementById("root"));
It turns out that I have older version of NodeJS and NPM.
Make sure you have node version >= 6: reference -> https://github.com/facebook/create-react-app#creating-an-app

Losing currentUser when App component refreshes?

I am currently working on a simple web app using React, Node.js, passport-google-oauth20.
For some reason, whenever the application re-mounts, I lose the currentUser state. It's as if req.user is just lost.
The way it works is I first fetch the current user when the application mounts and set this.state.currentUser to the results. The issue is when the page refreshes. The component re-mounts and I lose the user. I tried logging the user and receive null.
Hopefully I explained this well enough... here is the code:
App component:
import React from 'react';
import List from './List';
import ListForm from './ListForm';
import * as helpers from '../helpers';
class App extends React.Component{
state = {
currentUser: '',
}
componentDidMount() {
helpers.fetchUser()
.then(data => {
this.setState({
currentUser: data
});
});
}
onSubmit = (id, item) => {
helpers.addItem(id, item);
}
render() {
return (
<div className="container">
<List
currentUser={this.state.currentUser}
onSubmit={this.onSubmit}
/>
</div>
);
}
};
export default App;
Helpers:
import axios from 'axios';
export const fetchUser = async () => {
const resp = await axios.get('/api/current_user');
return resp.data;
}
export const addItem = (id, newItem) => {
axios.post("/api/" + id + "/addItem", newItem);
}

Resources