Search code examples
javascriptreactjsaxiosreact-bootstrap-table

Rendering axios response in React Bootstrap Table


Sorry, I know this is a newbie question, but I'm hoping someone can help.

I'm learning React and have a component todos-list.component.js which shows the results of an axios request and renders in a table and all is good (apart from some style issues which I'm not fussed about at the moment):

import React, { Component } from "react";
import { Link } from "react-router-dom";
import axios from "axios";

const Todo = (props) => (
  <tr>
    <td className={props.todo.todo_completed ? "completed" : ""}>
      {props.todo.todo_description}
    </td>
    <td className={props.todo.todo_completed ? "completed" : ""}>
      {props.todo.todo_responsible}
    </td>
    <td className={props.todo.todo_completed ? "completed" : ""}>
      {props.todo.todo_priority}
    </td>
    <td className={props.todo.todo_completed ? "completed" : ""}>
      {props.todo.todo_cardnumber}
    </td>
    <td className={props.todo.todo_completed ? "completed" : ""}>
      {props.todo.todo_playername}
    </td>
    <td className={props.todo.todo_completed ? "completed" : ""}>
      {props.todo.todo_teamname}
    </td>
    <td>
      <Link to={"/edit/" + props.todo._id}>Edit</Link>
    </td>
  </tr>
);

export default class TodosList extends Component {
  constructor(props) {
    super(props);
    this.state = { todos: [] };
  }

  componentDidMount() {
    axios
      .get(
        "https://webhooks.mongodb-realm.com/api/client/v2.0/app/todo-psiro/service/ToDo/incoming_webhook/todos"
      )
      .then((response) => {
        this.setState({ todos: response.data });
      })
      .catch(function (error) {
        console.log(error);
      });
  }

  componentDidUpdate() {
    axios
      .get(
        "https://webhooks.mongodb-realm.com/api/client/v2.0/app/todo-psiro/service/ToDo/incoming_webhook/todos"
      )
      .then((response) => {
        this.setState({ todos: response.data });
      })
      .catch(function (error) {
        console.log(error);
      });
  }

  todoList() {
    return this.state.todos.map(function (currentTodo, i) {
      return <Todo todo={currentTodo} key={i} />;
    });
  }

  render() {
    return (
      <div>
        <h3>Todos List</h3>
        <table className="table table-striped" style={{ marginTop: 20 }}>
          <thead>
            <tr>
              <th>Description</th>
              <th>Team Name</th>
              <th>Player Name</th>
              <th>Card Number</th>
              <th>Responsible</th>
              <th>Priority</th>
              <th>Actions</th>
            </tr>
          </thead>
          <tbody>{this.todoList()}</tbody>
        </table>
      </div>
    );
  }
}

I then have a different component table.component.js which renders static data into a React Bootstrap Table (https://react-bootstrap-table.github.io/react-bootstrap-table2/) and again this works fine:

import BootstrapTable from "react-bootstrap-table-next";
import paginationFactory from "react-bootstrap-table2-paginator";
import React, { Component } from "react";
import { Link } from "react-router-dom";
import axios from "axios";

const data = [
  {
    id: 0,
    name: "banana",
    price: "0.25",
  },
  {
    id: 1,
    name: "spinach",
    price: "4.49",
  },
  {
    id: 2,
    name: "icecream",
    price: "4.99",
  },
  {
    id: 3,
    name: "bagel",
    price: "1.19",
  },
  {
    id: 4,
    name: "fish",
    price: "10.00",
  },
];

const columns = [
  {
    dataField: "id",
    hidden: true,
  },
  {
    dataField: "name",
    text: "Grocery",
    sort: true,
  },
  {
    dataField: "price",
    text: "Price",
    formatter: (cell, row) => {
      return <p>${cell}</p>;
    },
    sort: true,
    sortFunc: (a, b, order, dataField, rowA, rowB) => {
      const numA = parseFloat(a);
      const numB = parseFloat(b);
      if (order === "asc") {
        return numB - numA;
      }
      return numA - numB; // desc
    },
  },
];

const BasicTable = () => {
  return (
    <BootstrapTable
      keyField="id"
      data={data}
      columns={columns}
      striped
      hover
      condensed
      pagination={paginationFactory({})}
    />
  );
};

export default BasicTable;

However what I would like to do is combine these so that the results of the axios GET request get rendered through the React Bootstrap Table. Can anyone help?


Solution

  • I'd suggest using a Function Component as the React ecysystem is moving towards that approach.

    You can use the useState hook to manage the state and the useEffect hook to make the API call.

    Something like this:

    import BootstrapTable from "react-bootstrap-table-next";
    import paginationFactory from "react-bootstrap-table2-paginator";
    import React, {
      useState,
      useEffect
    } from "react";
    import {
      Link
    } from "react-router-dom";
    import axios from "axios";
    
    const columns = [{
        dataField: "_id",
        hidden: true
      },
      {
        dataField: "todo_description",
        text: "Description",
        sort: true
      },
      {
        dataField: "todo_teamname",
        text: "Team Name",
        sort: true
      },
      {
        dataField: "todo_playername",
        text: "Player Name",
        sort: true
      },
      {
        dataField: "todo_cardnumber",
        text: "Card Number",
        sort: true
      },
      {
        dataField: "todo_responsible",
        text: "Responsible",
        sort: true
      },
      {
        dataField: "todo_priority",
        text: "Priority",
        sort: true
      },
      {
        dataField: "action",
        text: "Action"
      }
    ];
    
    const TableWithData = () => {
      const [data, setData] = useState([]);
    
      useEffect(() => {
        axios
          .get(
            "https://webhooks.mongodb-realm.com/api/client/v2.0/app/todo-psiro/service/ToDo/incoming_webhook/todos"
          )
          .then(response => {
            setData(response.data);
          })
          .catch(function(error) {
            console.log(error);
          });
      }, []);
    
      return ( <
        BootstrapTable keyField = "id"
        data = {
          data
        }
        columns = {
          columns
        }
        striped hover condensed pagination = {
          paginationFactory()
        }
        />
      );
    };
    
    export default TableWithData;
    

    Take a look at the TableWithData Component.

    Here's a Working Sample StackBlitz for your ref.