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

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.

Related

Pass parameter in React Url to get relative data

I created a express api where when we pass parameter to url say localhost:8000/data?music=rock it gives me data associated with it and if i pass say localhost:8000/data?music=rap and gives me data associated with it....P.S. there are many genre of music classical and so on and data associated with it.
Express api:: connected to mongoose where I scraped a data and stored in mongodb from where it feteches the data
app.get('/data'.(res,req)=>{
count music = req.query.music
collection.find({"music":music},(err,result)=>{
if(err):
return res.status(500).send(err);
}
else{
console.log(docs);
res.send(docs);
}
});
});
React JS::::
import React from "react";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {apiResponse:"",genre:""};
}
async callAPI(e) {
console.log(e.target.value);
const url = `http://localhost:8000/data?music=${e.target.value}`;
const response = await fetch(url);
console.log(response);
const textResponse = response.text();
console.log(textResponse);
this.setState({apiResponse:textResponse});
}
render() {
const {apiResponse} = this.state;
console.log(apiResponse);
return (
<>
<select name="continent" id="continent" onClick={e=>this.callAPI(e)}>
<option value=" ">--Please choose an option--</option>
<option value="Europe">Europe</option>
<option value="North America">North America</option>
</select>
{apiResponse && <h1>{apiResponse.title}</h1>}
</>
);
}
}
export default App;
Now i connected my express api with react but as you can see i have provided static path as
fetch("http://localhost:8000/data?music=Rock")
to get the data associated with rock music.
But I want react to fetch different genre of music dynamically from API without using a static path to fetch data. like react port:: localhost:3000/music=rock and it gives me data of rock music or classical and it gives me data of that.
Can anyone from community guide me on what method can be used or any article? Will be really appreciated. Cheers!!
You can use the select element to trigger an onChange event to fetch data from the user. Here, I replaced the url with template literals. After the fetch is complete and apiResponse is set, you can then map the data in the return block.
Here is a working sandbox.
import React from "react";
class App extends React.Component {
constructor(props) {
super(props);
this.state = { apiResponse: "", genre: "" };
}
async callAPI(e) {
console.log(e.target.value);
const url = `http://localhost:8000/data?music=${e.target.value}`;
const response = await fetch(url);
console.log(response);
const textResponse = response.text();
console.log(textResponse);
this.setState({ apiResponse: textResponse });
}
render() {
return (
<>
<select name="genre" id="genre" onChange={e => this.callAPI(e)}>
<option value="">--Please choose an option--</option>
<option value="Rap">Rap</option>
<option value="Rock">Rock</option>
</select>
</>
);
}
}
export default App;
You can use axis for the request and set the params, in this case, the music
axios.get('http://localhost:8000/data', {
params: {
music: 'rap'
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
.finally(function () {
// always executed
});
You can read more about axis here
You can add a controlled input field for music and use this.state.music in the fetch URL
https://reactjs.org/docs/forms.html#controlled-components

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

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.

Performing a fetch request only on state update

I'm new to React and I'm trying to figure out how to work with fetch correctly.
I have a React component that I'd like to update from a remote server whenever its parent's state updated.
i.e - parent's state changed -> myComponent calls remote server and re-renders itself.
I've tried the following:
If I only perform the .fetch call on componentDidMount, it disregards any state updates.
If I perform the .fetch call on componentDidUpdate as well it calls the server endlessly (I assume because of some update-render loop)
I have tried using the componentWillReceiveProps function, and it works, but I understand it's now deprecated.
How can I achieve this kind of behavior without componentWillReceiveProps ?
class myComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
images: []
};
}
componentDidMount() {
let server = "somethingserver.html";
fetch(server)
.then(res => {
if (res.ok) {
return res.json();
}
else {
console.log(res);
throw new Error(res.statusText);
}
})
.then(
(result) => {
this.setState({
images: result.items
});
}
).catch(error => console.log(error));
}
componentWillReceiveProps(nextprops) {
if (this.state !== nextprops.state) {
//same as componentDidMount
}
}
render() {
return (
<Gallery images={this.state.images} enableImageSelection={false} />
);
}
}
Given our conversation in the comments I can only assume that your search term is in a parent component. So what I recommend you to do is pass it to this component as a prop so you can do the following in your componentDid update:
componentDidUpdate(prevProps) {
const { searchTerm: previousSearch } = prevProps;
const { searchTerm } = this.props;
if (searchTerm !== previousSearch) fetch() ....
}
You can use getDerivedStateFromProps. It's the updated version of componentWillReceiveProps.
You should also read this, though: https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html
Using props to update internal state in a component can lead to complex bugs and there are often better solutions.

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

How to render data received from a REST service in React Universal? (Next.js)

I want to receive data via a REST service call in my React Universal (with Next.js) app using fetch() and then render the result into JSX like this:
class VideoPage extends Component {
componentWillMount() {
console.log('componentWillMount');
fetch(path, {
method: 'get',
})
.then(response =>
response.json().then(data => {
this.setState({
video: data,
});
console.log('received');
})
);
}
render() {
console.log('render');
console.log(this.state);
if (this.state && this.state.video) {
return (
<div>
{this.state.video.title}
</div>
);
}
}
}
export default VideoPage;
Unfortunately, the output is this:
componentWillMount
render
null
received
Which does make sense because the call to fetch is asynchronously and render() finishes before the call to the REST service has finished.
In a client-side app this would be no problem because a change of state would call render() which then updates the view, but in a universal app, especially with JavaScript turned off on the client, this is not possible.
How can I solve this?
Is there a way to call the server synchronously or delay render()?
In order to get it working, I had to do 3 things:
Replace componentWillMount with getInitialProps() method
Combine fetch with await and return the data
Use this.props instead of this.state
Code looks like this now:
static async getInitialProps({ req }) {
const path = 'http://path/to/my/service';
const res = await fetch(path);
const json = await res.json();
return { video: json };
}
Then, in render() I can access the data via this.props.video, for example:
render() {
return (
<div>{this.props.video.title}</div>
);
}
You can add static async getInitialProps () {} to load data into props before the page component gets rendered.
More info here: https://github.com/zeit/next.js/blob/master/readme.md#fetching-data-and-component-lifecycle

Resources