Home > Blockchain >  load the data dynamically by id on button click in ReactJS
load the data dynamically by id on button click in ReactJS

Time:10-02

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

  1. id was not passed as a param to fetchdata
  2. respnse data was JSON not an Array
  3. DO NOT call any function in componentDidUpdate without checking prev state. There was an infinite loop calling the API.
  4. 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;

enter image description here 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>

  • Related