import React,{Component} from 'react'
class Todo extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
fetchdata: [],
};
}
componentDidMount() {
fetch("https://jsonplaceholder.typicode.com/todos")
.then((res) => res.json())
.then((json) => {
this.setState({
data: json,
});
});
}
componentDidUpdate(){
this.fetchdata();
}
fetchdata=()=>{
fetch("https://jsonplaceholder.typicode.com/users/:id")
.then((res) => res.json())
.then((json) => {
this.setState({
fetchdata: json.data,
});
});
}
render() {
const { data, fetchdata } = this.state;
return (
<div>
<div className="Todos row g-3">
<table class="table col-auto">
<thead>
<tr>
<th scope="col">Todo</th>
<th scope="col">Title</th>
<th scope="col">Status</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
{this.state.data.map((data, index) => (
<tr key={index}>
<th scope="row">{data.id}</th>
<td>{data.title}</td>
<td>{data.completed}</td>
<td>
<button onClick={this.fetchdata.bind(this, data)}>
View
</button>
</td>
</tr>
))}
;
</tbody>
</table>
</div>
<div className="show-data col-auto">
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Todo_Id</th>
<th scope="col">Todo_title</th>
<th scope="col">User_id</th>
</tr>
</thead>
<tbody>
{this.state.fetchdata.map((fetchdata, index) => (
<tr key={index}>
<th scope="row">{fetchdata.id}</th>
<td>{fetchdata.name}</td>
<td>{fetchdata.email}</td>
</tr>
))}
;
</tbody>
</table>
</div>
</div>
);
}
}
export default Todo
This is my code I want to load data on button click but I am getting an error: "Cannot read properties of undefined (reading 'map') ". I am new to react js and don't know how to do it. The data is not getting loaded in the below table on button click by id. The first table data is loading correctly.
CodePudding user response:
There were few issues
id
was not passed as a param tofetchdata
- respnse data was
JSON
not anArray
- DO NOT call any function in
componentDidUpdate
without checking prev state. There was an infinite loop calling the API. - No need to bind
fetchdata
function as it is an arrow function.
import React, { Component } from "react";
class Todo extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
fetchdata: []
};
}
componentDidMount() {
fetch("https://jsonplaceholder.typicode.com/todos")
.then((res) => res.json())
.then((json) => {
this.setState({
data: json
});
});
}
fetchdata = (id) => {
console.log(id);
fetch(`https://jsonplaceholder.typicode.com/users/${id}`)
.then((res) => res.json())
.then((json) => {
console.log(json);
this.setState({
fetchdata: json
});
});
};
render() {
const { data, fetchdata } = this.state;
return (
<div>
<div className="Todos row g-3">
<table class="table col-auto">
<thead>
<tr>
<th scope="col">Todo</th>
<th scope="col">Title</th>
<th scope="col">Status</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
{this.state.data.map((data, index) => (
<tr key={index}>
<th scope="row">{data.id}</th>
<td>{data.title}</td>
<td>{data.completed}</td>
<td>
<button onClick={() => this.fetchdata(data.id)}>
View
</button>
</td>
</tr>
))}
;
</tbody>
</table>
</div>
<div className="show-data col-auto">
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Todo_Id</th>
<th scope="col">Todo_title</th>
<th scope="col">User_id</th>
</tr>
</thead>
<tbody>
{this.state.fetchdata && (
<tr>
<th scope="row">{fetchdata.id}</th>
<td>{fetchdata.name}</td>
<td>{fetchdata.email}</td>
</tr>
)}
</tbody>
</table>
</div>
</div>
);
}
}
export default Todo;
Sandbox code => https://codesandbox.io/s/pensive-parm-c0l54?file=/src/App.js:0-2277
CodePudding user response:
If you are new to react i highly recommend you to use hooks, but there are several things you can do in your Code:
1-Fetch data(you need id i Think, so):
fetchdata=(id)=>{
fetch(https://jsonplaceholder.typicode.com/users/${id}
)
.then((res) => res.json())
.then((json) => {
this.setState({
fetchdata: json.data,
});
});
}
This Way you pass the id by arguments.
2- onClick función: View As you Will need the id to pass it to the fetch función. No need bina with fan Arrow function
3- This is the Code i suggest for hooks:
import React, {useState, useEffect} from "react";
const Todo = () => {
const [data, setData] = useState([])
const [fetchdata,setFetchdata] = useState([])
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/todos")
.then((res) => res.json())
.then((json) => {
setData(json);
});
},[])
const fetchdataById = (id) => {
console.log(id);
fetch(`https://jsonplaceholder.typicode.com/users/${id}`)
.then((res) => res.json())
.then((json) => {
console.log(json);
setFetchdata(json)
});
};
return (
<div>
<div className="Todos row g-3">
<table class="table col-auto">
<thead>
<tr>
<th scope="col">Todo</th>
<th scope="col">Title</th>
<th scope="col">Status</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
{data.map((data, index) => (
<tr key={index}>
<th scope="row">{data.id}</th>
<td>{data.title}</td>
<td>{data.completed}</td>
<td>
<button onClick={() => fetchdataById(data.id)}>
View
</button>
</td>
</tr>
))}
;
</tbody>
</table>
</div>
<div className="show-data col-auto">
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Todo_Id</th>
<th scope="col">Todo_title</th>
<th scope="col">User_id</th>
</tr>
</thead>
<tbody>
{fetchdata && (
<tr>
<th scope="row">{fetchdata.id}</th>
<td>{fetchdata.name}</td>
<td>{fetchdata.email}</td>
</tr>
)}
</tbody>
</table>
</div>
</div>
);
}
export default Todo;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Something like this should Work,
CodePudding user response:
here's what you can do:
class Todo extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
fetchdata: {}
};
}
componentDidMount() {
fetch("https://jsonplaceholder.typicode.com/todos")
.then((res) => res.json())
.then((json) => {
this.setState({
data: json
});
});
}
fetchdata = (todo) => {
fetch("https://jsonplaceholder.typicode.com/users/" todo.id)
.then((res) => res.json())
.then((json) => {
this.setState({
fetchdata: json
});
});
};
render() {
const { data, fetchdata } = this.state;
return (
<div>
<div className="Todos row g-3">
<table className="table col-auto">
<thead>
<tr>
<th scope="col">Todo</th>
<th scope="col">Title</th>
<th scope="col">Status</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
{data.map((todo, index) => (
<tr key={index}>
<th scope="row">{todo.id}</th>
<td>{todo.title}</td>
<td>{todo.completed}</td>
<td>
<button onClick={() => this.fetchdata(todo)}>View</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
<div className="show-data col-auto">
<table className="table table-striped">
<thead>
<tr>
<th scope="col">Todo_Id</th>
<th scope="col">Todo_title</th>
<th scope="col">User_id</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">{fetchdata.id}</th>
<td>{fetchdata.name}</td>
<td>{fetchdata.email}</td>
</tr>
</tbody>
</table>
</div>
</div>
);
}
}
ReactDOM.render(
<Todo />,
document.body
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>