REACT GET requiest getting base url twice - reactjs

Using REACT front-end with Django back-end. When i call request api i can see it being pulled correctly, however when onClick is called i get a 404 XHRGEThttp://localhost:3000/http//127.0.0.1:8000/undefined so it seems that i am somehow calling the base url twice but i am not sure how?
here is my main component file:
import React, { Component } from 'react';
import SubtagsList from './list_subtags';
import axios from 'axios';
class TagsList extends Component {
constructor(props) {
super(props);
this.state = {
tagData: [],
subtags: " ",
showComponent: false,
}
this.getSubtagDetail = this.getSubtagDetail.bind(this);
this.showSubtags = this.showSubtags.bind(this);
}
getSubtagDetail(item){
axios.get("http//127.0.0.1:8000/".concat(item.absolute_url))
.then((response) =>{
this.setState({subtags: response.data})
})
.catch(function(error){
console.log(error);
})
}
showSubtags(item){
this.getSubtagDetail(item);
this.setState({showComponent: true})
}
componentDidMount(){
axios.get("http://127.0.0.1:8000/")
.then( (response) => {
this.setState({tagData: response.data})
})
.catch(function(error) {
console.log(error);
})
}
render() {
return (
<div>
{this.state.tagData.map((item) => {
return (
<h3 key={item.id} onClick={() => this.showSubtags(item)}>
{item.tag_name}
</h3>
);
})}
{this.state.showComponent ? (
<SubtagsList subtagDetail={this.state.subtags} />
) : null}
</div>
)
}
}
export default TagsList;
here is the api response:
[
{
"id": 2,
"tag_name": "IT/Computer Issues",
"type": "Tag"
},
{
"id": 1,
"subtag_name": "Website",
"absolute_url": "/1",
"type": "SubTag"
}
]
and this is the SubtagsList component imported:
import React, { Component } from 'react';
class SubtagsList extends Component {
render() {
const obj = this.props.subtagDetail;
return (
<div style={{ color: "yellow", border: "1px solid yellow" }}>
<p>{obj.subtag_name}</p>
</div>
)
}
}
export default SubtagsList;
Can anyone shed some light on what i might be doing wrong here?

Related

React, How to use a menu in a seperate file to call an api and return data to a different section of the main file

I have a react app with a large menu, and as such am trying to move it to a seperate file from the main app.js
at the mement when you click on a link in the menu it call a node api and which returns some data, however when I try to seperate I can not get it to populate the results section which is still in the main script
Working version app.js
import React,{ useState } from 'react';
import './App.css';
import axios from 'axios';
import { Navigation } from "react-minimal-side-navigation";
import "react-minimal-side-navigation/lib/ReactMinimalSideNavigation.css";
export default class MyList extends React.Component {
constructor(props) {
super(props);
this.state = {
result: [],
};
this.callmyapi = this.callmyapi.bind(this);
}
render() {
return (
<div>
<div class="menu">
<Navigation
onSelect={({itemId}) => {
axios.get(`/api/menu/`, {
params: {
Menu: itemId,
}
})
.then(res => {
const results = res.data;
this.setState({ results });
})
.catch((err) => {
console.log(err);
})
}}
items={[
{
title: 'Pizza',
itemId: '/menu/Pizza/',
},
{
title: 'Cheese',
itemId: '/menu/cheese',
}
]}
/>
</div>
<div class="body">
this.state.results && this.state.results.map(results => <li>* {results.Name}</li>);
</div>
</div>
);
}
}
New app.js
import React,{ useState } from 'react';
import './App.css';
//import axios from 'axios';
//import { Navigation } from "react-minimal-side-navigation";
//import "react-minimal-side-navigation/lib/ReactMinimalSideNavigation.css";
import MyMenu from './mymenu';
export default class MyList extends React.Component {
constructor(props) {
super(props);
this.state = {
result: [],
};
this.callmyapi = this.callmyapi.bind(this);
}
render() {
return (
<div>
<div class="menu">
<MyMenu />
</div>
<div class="body">
this.state.results && this.state.results.map(results => <li>* {results.Name}</li>);
</div>
</div>
);
}
}
New menu file
mymenu.js
import React, { Component } from 'react';
import axios from 'axios';
import './App.css';
//import MyList from './App.js';
//import { ProSidebar, Menu, MenuItem, SubMenu } from 'react-pro-sidebar';
//import 'react-pro-sidebar/dist/css/styles.css';
import { Navigation } from "react-minimal-side-navigation";
//import Icon from "awesome-react-icons";
import "react-minimal-side-navigation/lib/ReactMinimalSideNavigation.css";
//export default async function MyMenu(){
export default class MyMenu extends React.Component {
constructor(props) {
super(props);
};
render() {
return (
<div>
<Navigation
// you can use your own router's api to get pathname
activeItemId="/management/members"
onSelect={({itemId}) => {
// return axios
axios.get(`/api/menu/`, {
params: {
// Menu: itemId,
Menu: "meat",
SubMenu : "burgers"
}
})
.then(res => {
const results = res.data;
this.setState({ results });
})
.catch((err) => {
console.log(err);
})
}}
items={[
{
title: 'Pizza',
itemId: '/menu/Pizza/',
},
{
title: 'Cheese',
itemId: '/menu/cheese',
}
]}
/>
</div>
);
}
}
Any help would be greatly appreciated
That one is quite easy once you understand state. State is component specific it that case. this.state refers to you App-Component and your Menu-Component individually. So in order for them to share one state you have to pass it down the component tree like this.
export default class MyList extends React.Component {
constructor(props) {
super(props);
this.state = {
result: [],
};
}
render() {
return (
<div>
<div class="menu">
<MyMenu handleStateChange={(results: any[]) => this.setState(results)} />
</div>
<div class="body">
this.state.results && this.state.results.map(results => <li>* {results.Name}</li>);
</div>
</div>
);
}
}
See this line: <MyMenu handleStateChange={(results: any[]) => this.setState(results)} />
There you pass a function to mutate the state of App-Component down to a the child
There you can call:
onSelect={({itemId}) => {
// return axios
axios.get(`/api/menu/`, {
params: {
// Menu: itemId,
Menu: "meat",
SubMenu : "burgers"
}
})
.then(res => {
const results = res.data;
this.props.handleStateChange(results)
})
.catch((err) => {
console.log(err);
})
You mutate the parent state and the correct data is being rendered. Make sure to practice state and how it works and how usefull patterns look like to share state between components.
Thanks - I Have found solution (also deleted link question)
above render added function
handleCallback = (results) =>{
this.setState({data: results})
}
then where I display the menu
<MyMenu parentCallback = {this.handleCallback}/>
where i display the results
{this.state.results && this.state.results.map(results => <li>{results.Name}</li>}
No aditional changes to the menu scripts

Using ReactJs to fetch data from an api but getting a blank page with no error

Hello Guys kindly someone assist me with the issue i am having with my code. I am a newbie trying to learn react. i am trying to fetch data from an api. From the browser console i can see the data but when i try to return the data in the Dom i get a blank page. see my code below.
import React, { Component } from "react";
class FetchApi extends Component {
constructor(props) {
super(props);
this.state = {
person: []
};
}
componentDidMount() {
fetch("https://api.randomuser.me/")
.then(res => res.json())
.then(data => console.log(data))
.then(data => {
this.setState({
person: data
});
});
}
render() {
return (
<div>
{this.state.person &&
this.state.person.map(item => (
<li key={item.results.id}>
{item.results.gender} {item.results.location}
</li>
))}
</div>
);
}
}
export default FetchApi;
I have modified your code to the following. In some cases the way you are referencing the properties was wrong. Have made some changes in your componentDidMount and in the render method.
Sandbox for your reference: https://codesandbox.io/s/react-basic-example-nubu7
Hope this resolves
import React, { Component } from "react";
class App extends Component {
constructor(props) {
super(props);
this.state = {
person: []
};
}
componentDidMount() {
try {
fetch("https://api.randomuser.me/")
.then(res => res.json())
.then(data => {
this.setState({
person: data.results
});
});
} catch (e) {
console.log(e);
}
}
render() {
return (
<div>
{this.state.person &&
this.state.person.map(item => (
<li key={item.id.value}>
{item.gender} {item.location.city}
</li>
))}
</div>
);
}
}
export default App;
Check this codesandbox, the response from the fetch API is in this format
{
"results":[
{
"gender":"male",
"name":{
"title":"Monsieur",
"first":"Alois",
"last":"Fernandez"
},
"location":{
"street":{
"number":1856,
"name":"Rue Duquesne"
},
"city":"Untereggen",
"state":"Genève",
"country":"Switzerland",
"postcode":9650,
"coordinates":{
"latitude":"-50.1413",
"longitude":"-23.6337"
},
"timezone":{
"offset":"+5:30",
"description":"Bombay, Calcutta, Madras, New Delhi"
}
},
"email":"alois.fernandez#example.com",
"login":{
"uuid":"04b2ee45-cf07-4015-a5d8-2311f6dc28a1",
"username":"ticklishleopard228",
"password":"forward",
"salt":"V8bDcgux",
"md5":"d521c6488fc4644ccb7e670e9e67bc20",
"sha1":"9673afe219f27817c573a9cb727c209357d386ef",
"sha256":"c13a5bc77dc720a6cc46bc640680e9501225fc94c9bc6ba7fe203fe989a992a0"
},
"dob":{
"date":"1957-11-24T13:46:29.422Z",
"age":63
},
"registered":{
"date":"2003-05-18T19:56:11.397Z",
"age":17
},
"phone":"077 871 56 07",
"cell":"077 461 83 98",
"id":{
"name":"AVS",
"value":"756.1050.9271.56"
},
"picture":{
"large":"https://randomuser.me/api/portraits/men/8.jpg",
"medium":"https://randomuser.me/api/portraits/med/men/8.jpg",
"thumbnail":"https://randomuser.me/api/portraits/thumb/men/8.jpg"
},
"nat":"CH"
}
],
"info":{
"seed":"76a6b875b2ba81dd",
"results":1,
"page":1,
"version":"1.3"
}
}
So you have to set the person in the state to data.results instead of data and access the item in the results accordingly.

How to pass data to props from state?

I'm learning React and have some troubles with using state and props. There is two files: App.js and component. In App.js i use axios to get JSON data from IP and store in a state. But I cannot pass the data to props through the state.
Here is App.js:
import React from 'react';
import axios from 'axios';
import Shutruk from './Shutruk';
const qwerty = {
"data": [
{
"_id": "5d1cb18e4af03042df6267c5",
"title": "Shutruk",
"description": "Shhhhhhhhhhhhh",
"date": "2019-07-03T13:45:50.850Z",
"__v": 0
},
{
"_id": "5d1cc27b37c9751001f5c12f",
"title": "Shilkhak",
"description": "Shilkhak-Inshushinak",
"date": "2019-07-03T14:58:03.797Z",
"__v": 0
},
{
"_id": "5d1cc45655780f11112a023f",
"title": "Унташ",
"description": "Untash-Napirisha",
"date": "2019-07-03T15:05:58.699Z",
"__v": 0
},
{
"_id": "5d1ef36c503601183b5f856f",
"title": "dgfdgfdhgf",
"description": "bbbbbbbbbbbbbbbbb",
"date": "2019-07-05T06:51:24.873Z",
"__v": 0
},
{
"_id": "5d1ef381503601183b5f8570",
"title": "qewytuytruytru",
"description": "jhfgasjdfgasjdfgjhsdf",
"date": "2019-07-05T06:51:45.761Z",
"__v": 0
}
]
};
class App extends React.Component {
state = {
data: []
}
componentDidMount() {
axios.get('http://localhost:5555/posts')
.then(res => {
const data = res.data;
this.setState({ data });
})
}
render() {
return (
<div>
<Shutruk name={ this.state.data.data[0].title }/>
</div>
)
}
}
export default App;
Here is the component:
import React from 'react';
class Shutruk extends React.Component {
render() {
return (
<div>
<h1>This is is {this.props.name}!</h1>
</div>
)
}
}
export default Shutruk;
I use axios to get data from backend, but when I insert it to props, it does'nt work. I create an array qwerty[] with the same data, and when I replace with:
return (
<div>
<Shutruk name={ qwerty.data[0].title }/>
</div>
)
it works correctly. What is the problem, if there is no difference between 'this.state.data' and 'qwerty'?
I checked with console.log and the result is same!
Thanks to everyone for any help!
This is because, axios and setState are asynchronous and when the component loads in componentDidMount, it takes a while to load data into state and since data.data[0] is still empty, it doesn't work. But when you use a const to declare it, it works as it is already present.
Instead of
<Shutruk name={ this.state.data.data[0].title }/>
Do:
renderShutruk = () => {
if (this.state.data.data !== undefined) {
return <Shutruk name={this.state.data.data[0].title} />
} else {
return null;
}
};
render() {
return (
<div>
{this.renderShutruk()}
</div>
);
}
Your App component is probably crashing when mounting while you're accessing an undefined state because your try to get this.state.data.data[0].title when data state equals []
Try replacing your App component like this to prevent access to an undefined state (I recommend doing this for all your asynchronous operations in the components):
class App extends React.Component {
state = {
data: [],
loading: true,
error: false,
}
componentDidMount() {
axios.get('http://localhost:5555/posts')
.then(res => {
const data = res.data.data; // get the data array instead of object
this.setState({ data, loading: false });
})
.catch(err => { // log request error and prevent access to undefined state
this.setState({ loading: false, error: true });
console.error(err);
}
render() {
if (this.state.loading) {
return(
<div>
<p> Loading... </p>
</div>
)
}
if (this.state.error || !this.state.data[0]) { // if request failed or data is empty don't try to access it either
return(
<div>
<p> An error occurred </p>
</div>
)
}
return (
<div>
<Shutruk name={ this.state.data[0].title }/> // access to data array state
</div>
)
}
}
export default App;
Just change this,
<Shutruk name={ this.state.data.data[0].title }/>
with,
{this.state.data ? <Shutruk name={ this.state.data[0].title }/> : null}
Update
If you are not getting data, then you must use async/await,
async componentDidMount() {
await axios.get('http://localhost:5555/posts')
.then(res => {
//console.log(res) => if `res` is {data:[...]} , then do this,
const data = res.data;
//console.log(res) => if `res` is {data: data: [...]} , then do this,
const data = res.data.data;
this.setState({ data });
})
}

quagga-react barcode scanner

Essentially I get the demo to work save for the actual scanning. i.e. camera is on etc. Not sure what I am missing...
Here is my code.
App.js file:
import React, { Component } from 'react';
import Scanner from './Scanner';
import Result from './Result';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
scanning: false,
results: [],
};
this._scan = this._scan.bind(this);
this._onDetected = this._onDetected.bind(this);
}
_scan() {
this.setState({ scanning: !this.state.scanning });
}
_onDetected(result) {
this.setState({ results: this.state.results.concat([result]) });
}
render() {
return (
<div>
<button onClick={this._scan}>{this.state.scanning ? 'Stop' : 'Start'}</button>
<ul className="results">
{this.state.results.map(result => {
<Result key={result.codeResult.code} result={result} />;
})}
</ul>
{this.state.scanning ? <Scanner onDetected={this.state._onDetected} /> : null}
</div>
);
}
}
Scanner.js file:
import React, { Component } from 'react';
import Quagga from 'quagga';
export default class Scanner extends Component {
constructor(props) {
super(props);
this._onDetected = this._onDetected.bind(this);
}
componentDidMount() {
Quagga.init(
{
inputStream: {
type: 'LiveStream',
constraints: {
width: 640,
height: 480,
facingMode: 'environment', // or user
},
},
locator: {
patchSize: 'medium',
halfSample: true,
},
numOfWorkers: 2,
decoder: {
readers: ['upc_reader'],
},
locate: true,
},
function(err) {
if (err) {
return console.log(err);
}
Quagga.start();
}
);
Quagga.onDetected(this._onDetected);
}
componentWillUnmount() {
Quagga.offDetected(this._onDetected);
}
_onDetected(result) {
this.props.onDetected(result);
}
render() {
return <div id="interactive" className="viewport" />;
}
}
Result.js file:
import React, { Component } from 'react';
export default class Result extends Component {
render() {
const result = this.props.result;
if (!result) {
return null;
}
return (
<li>
{result.codeResult.code} [{result.codeResult.format}]
</li>
);
}
}
Thanks my friends!
You may want to change the reader type, which is code_128_reader by default.
Most barcodes used in supermarkets for example follow the EAN specification (at least where I live), so you can put this in Scanner.js to change to an ean_reader:
decoder: {
readers: ["ean_reader"]
},
where Quagga is initiated.
A list of readers can be found here: Quagga documentation.
If this doesn't work, I would advise to try other reader / barcode combinations.
The documentation says that in Node you should use numOfWorkers: 0
https://serratus.github.io/quaggaJS/#node-example
add /* eslint-disable */ in to return .
{
/* eslint-disable */
this.state.results.map(result => {
<Result key={result.codeResult.code} result={result} />;
})}
</ul>
Might be too late to answer, will leave it here in case anyone would be interested.
I was able to make it work. There were few issues I had to resolve:
Applied different decoder as rpld suggested:
decoder: {
readers: ["ean_reader"]
},
Fix TypeError: this.props.onDetected is not a function. In App.js adjusted the following line:
From:
{this.state.scanning ? <Scanner onDetected={this.state._onDetected} /> : null}
To:
{this.state.scanning ? <Scanner onDetected={(result) => this._onDetected(result)} /> : null}
I also used Quagga2, but don't know if it makes any difference in this case.
Leaving full version of working code, just in case.
App.js:
import React, { Component } from 'react';
import Scanner from './Scanner';
import Result from './Result';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
scanning: false,
results: []
};
this._scan = this._scan.bind(this);
this._onDetected = this._onDetected.bind(this);
}
_scan() {
this.setState({ scanning: !this.state.scanning });
}
_onDetected(result) {
this.setState({ results: this.state.results.concat([result]) });
}
render() {
return (
<div>
<button onClick={this._scan}>{this.state.scanning ? 'Stop' : 'Start'}</button>
<ul className="results">
{this.state.results.map((result, idx) => {
return (<Result key={result.codeResult.code} result={result} />)
})}
</ul>
{this.state.scanning ? <Scanner onDetected={(result) => this._onDetected(result)} /> : null}
</div>
);
}
}
Scanner.js:
import React, { Component } from 'react';
import Quagga from '#ericblade/quagga2';
export default class Scanner extends Component {
constructor(props) {
super(props);
this._onDetected = this._onDetected.bind(this);
}
componentDidMount() {
Quagga.init(
{
inputStream: {
type: 'LiveStream',
constraints: {
width: 640,
height: 480,
facingMode: 'environment', // or user
},
},
locator: {
patchSize: 'medium',
halfSample: true,
},
numOfWorkers: 0,
decoder: {
readers: ['ean_reader'],
},
locate: true,
},
function(err) {
if (err) {
return console.log(err);
}
Quagga.start();
}
);
Quagga.onDetected(this._onDetected);
}
componentWillUnmount() {
Quagga.offDetected(this._onDetected);
}
_onDetected(result) {
this.props.onDetected(result);
}
render() {
return <div id="interactive" className="viewport" />;
}
}
Result.js (not touched at all):
import React, { Component } from 'react';
export default class Result extends Component {
render() {
const result = this.props.result;
if (!result) {
return null;
}
return (
<li >
{result.codeResult.code} [{result.codeResult.format}]
</li>
);
}
}

React setState fetch API

I am starting to learn React and creating my second project at the moment. I am trying to usi MovieDb API to create a movie search app. Everything is fine when I get the initial list of movies. But onClick on each of the list items I want to show the details of each movie. I have created a few apps like this using vanilla JS and traditional XHR call. This time I am using fetch API which seems straightforward ans simply to use, however when I map through response data to get id of each movie in order to retrieve details separately for each of them I get the full list of details for all the items, which is not the desired effect. I put the list of objects into an array, because after setState in map I was only getting the details for the last element. I know that I am probably doing something wrong within the API call but it might as well be my whole REACT code. I would appreciate any help.
My code
App.js
import React, { Component } from 'react';
import SearchInput from './Components/SearchInput'
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state =
{
value: '',
showComponent: false,
results: [],
images: {},
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleOnChange = this.handleOnChange.bind(this);
this.getImages = this.getImages.bind(this);
this.getData = this.getData.bind(this);
}
ComponentWillMount() {
this.getImages();
this.getData();
}
getImages(d) {
let request = 'https://api.themoviedb.org/3/configuration?api_key=70790634913a5fad270423eb23e97259'
fetch(request)
.then((response) => {
return response.json();
}).then((data) => {
this.setState({
images: data.images
});
});
}
getData() {
let request = new Request('https://api.themoviedb.org/3/search/movie?api_key=70790634913a5fad270423eb23e97259&query='+this.state.value+'');
fetch(request)
.then((response) => {
return response.json();
}).then((data) => {
this.setState({
results: data.results
});
});
}
handleOnChange(e) {
this.setState({value: e.target.value})
}
handleSubmit(e) {
e.preventDefault();
this.getImages();
this.setState({showComponent: true});
this.getData();
}
render() {
return (
<SearchInput handleSubmit={this.handleSubmit} handleOnChange={this.handleOnChange} results={this.state.results} images={this.state.images} value={this.state.value} showComponent={this.state.showComponent}/>
);
}
}
export default App;
SearchInput.js
import React, {Component} from 'react';
import MoviesList from './MoviesList';
class SearchInput extends Component {
render() {
return(
<div className='container'>
<form id='search-form' onSubmit={this.props.handleSubmit}>
<input value={this.props.value} onChange={this.props.handleOnChange} type='text' placeholder='Search movies, tv shows...' name='search-field' id='search-field' />
<button type='submit'>Search</button>
</form>
<ul>
{this.props.showComponent ?
<MoviesList value={this.props.value} results={this.props.results} images={this.props.images}/> : null
}
</ul>
</div>
)
}
}
export default SearchInput;
This is the component where I try to fetch details data
MovieList.js
import React, { Component } from 'react';
import MovieDetails from './MovieDetails';
let details = [];
class MoviesList extends Component {
constructor(props) {
super(props);
this.state = {
showComponent: false,
details: []
}
this.showDetails = this.showDetails.bind(this);
this.getDetails = this.getDetails.bind(this);
}
componentDidMount() {
this.getDetails();
}
getDetails() {
let request = new Request('https://api.themoviedb.org/3/search/movie?api_key=70790634913a5fad270423eb23e97259&query='+this.props.value+'');
fetch(request)
.then((response) => {
return response.json();
}).then((data) => {
data.results.forEach((result, i) => {
let url = 'https://api.themoviedb.org/3/movie/'+ result.id +'?api_key=70790634913a5fad270423eb23e97259&append_to_response=videos,images';
return fetch(url)
.then((response) => {
return response.json();
}).then((data) => {
details.push(data)
this.setState({details: details});
});
});
console.log(details);
});
}
showDetails(id) {
this.setState({showComponent: true}, () => {
console.log(this.state.details)
});
console.log(this.props.results)
}
render() {
let results;
let images = this.props.images;
results = this.props.results.map((result, index) => {
return(
<li ref={result.id} id={result.id} key={result.id} onClick={this.showDetails}>
{result.title}{result.id}
<img src={images.base_url +`${images.poster_sizes?images.poster_sizes[0]: 'err'}` + result.backdrop_path} alt=''/>
</li>
)
});
return (
<div>
{results}
<div>
{this.state.showComponent ? <MovieDetails details={this.state.details} results={this.props.results}/> : null}
</div>
</div>
)
}
}
export default MoviesList;
MovieDetails.js
import React, { Component } from 'react';
class MovieDetails extends Component {
render() {
let details;
details = this.props.details.map((detail,index) => {
if (this.props.results[index].id === detail.id) {
return(
<div key={detail.id}>
{this.props.results[index].id} {detail.id}
</div>
)} else {
console.log('err')
}
});
return(
<ul>
{details}
</ul>
)
}
}
export default MovieDetails;
Theres a lot going on here...
//Here you would attach an onclick listener and would fire your "get details about this specific movie function" sending through either, the id, or full result if you wish.
//Then you getDetails, would need to take an argument, (the id) which you could use to fetch one movie.
getDetails(id){
fetch(id)
displayresults, profit
}
results = this.props.results.map((result, index) => {
return(
<li onClick={() => this.getDetails(result.id) ref={result.id} id={result.id} key={result.id} onClick={this.showDetails}>
{result.title}{result.id}
<img src={images.base_url +`${images.poster_sizes?images.poster_sizes[0]: 'err'}` + result.backdrop_path} alt=''/>
</li>
)
});
Thanks for all the answers but I have actually maanged to sort it out with a bit of help from a friend. In my MovieList I returned a new Component called Movie for each component and there I make a call to API fro movie details using each of the movie details from my map function in MovieList component
Movielist
import React, { Component } from 'react';
import Movie from './Movie';
class MoviesList extends Component {
render() {
let results;
if(this.props.results) {
results = this.props.results.map((result, index) => {
return(
<Movie key={result.id} result={result} images={this.props.images}/>
)
});
}
return (
<div>
{results}
</div>
)
}
}
export default MoviesList;
Movie.js
import React, { Component } from 'react';
import MovieDetails from './MovieDetails';
class Movie extends Component {
constructor(props) {
super(props);
this.state = {
showComponent: false,
details: []
}
this.showDetails = this.showDetails.bind(this);
this.getDetails = this.getDetails.bind(this);
}
componentDidMount() {
this.getDetails();
}
getDetails() {
let request = new Request('https://api.themoviedb.org/3/search/movie?api_key=70790634913a5fad270423eb23e97259&query='+this.props.value+'');
fetch(request)
.then((response) => {
return response.json();
}).then((data) => {
let url = 'https://api.themoviedb.org/3/movie/'+ this.props.result.id +'?api_key=70790634913a5fad270423eb23e97259&append_to_response=videos,images';
return fetch(url)
}).then((response) => {
return response.json();
}).then((data) => {
this.setState({details: data});
});
}
showDetails(id) {
this.setState({showComponent: true}, () => {
console.log(this.state.details)
});
}
render() {
return(
<li ref={this.props.result.id} id={this.props.result.id} key={this.props.result.id} onClick={this.showDetails}>
{this.props.result.title}
<img src={this.props.images.base_url +`${this.props.images.poster_sizes?this.props.images.poster_sizes[0]: 'err'}` + this.props.result.backdrop_path} alt=''/>
{this.state.showComponent ? <MovieDetails details={this.state.details}/> : null}
</li>
)
}
}
export default Movie;

Resources