I use axios to create my datatatable using MUIDataTable in my React JS. but with my code the result is just show empty table..
in code below i dont know where i should change, because the result is empty table without data result as in JSON.why const data cant be read, anyone can help?
here's my code
App.js
import React,{Component} from "react";
import ReactDOM from "react-dom";
import MUIDataTable from "mui-datatables";
import axios from "axios";
import { Link } from 'react-router-dom';
class App extends Component {
// State will apply to the posts object which is set to loading by default
constructor(props) {
super(props);
this.state = {
data: [],
isLoading: true,
errors: null,
};
}
// Now we're going to make a request for data using axios
getData = async () => {
const option = {
url: "url/api",
method: 'POST',
data: {
"data": {
"name": "...",
"id":"..."
},
"encrypt": 0
}
};
axios(option)
.then(response => {
this.setState({
data: response.data.data,
isLoading: false,
});
console.log(response.data);
})
// If we catch any errors connecting, let's update accordingly
.catch(error => {
console.log(error.response);
this.setState({ error, isLoading: false })
}
);
}
// Let's our app know we're ready to render the data
componentDidMount() {
this.getData();
}
// Putting that data to use
render() {
const { isLoading, data } = this.state;
const columns = ["ID","Name];
const options = {
filterType: "dropdown",
responsive: "scroll",
selectableRows:false
};
return (
<div>
<center><h3>List Data</h3></center><br/>
<MUIDataTable
columns={columns}
options={options}
data={data}
/>
{!isLoading ? (
data.map(post => {
const {id, name} = post;
const data = [
[
{id},
{name}
})
) : (
<p>Loading...</p>
)}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
export default App
Your option is wrong. url should be outside of the option. the correct order is:
axios.post('url' , options , headers).This may be helpful.For more info please visit https://github.com/axios/axios.
Related
I'm unable to update the state using the axios response in a class component. It works just fine with function based components. Could somebody please point out what is causing this issue. I'm new to react and tried most of the possible answers out there.
code :
import React, { Component } from "react";
import "./Table.css";
import { Button } from "./Button";
import { Table } from "react-bootstrap";
import axios from "axios";
import Example from "./Progress";
class Tables extends Component {
constructor(props) {
super(props);
this.state = {
submitted: false,
task_id: "",
};
this.handlesubmit = this.handlesubmit.bind(this);
}
handlesubmit(event) {
var self = this;
event.preventDefault();
axios({
method: "post",
url: "http://127.0.0.1:8000/api/test/",
data: {
project_name: "test",
},
}).then(function (response) {
console.log(response.data.task_id); //prints taskid (12345678)
self.setState({
task_id: response.data.task_id,
});
console.log(self.task_id); //prints undefined
});
this.setState({ submitted: true }); //works fine, state is set to true
console.log(this.task_id); //prints undefined
}
render() {
let modal;
let task_id = this.state.task_id;
let submitted = this.state.submitted;
if (submitted === true) {
modal = <Example pro="test" task={task_id} />;
}
return (
<div className="table-div">
<Button
buttonStyle="btn--secondary"
buttonSize="btn--small--opt"
onClick={this.handlesubmit}
>
test
</Button>
{modal}
</div>
);
}
}
export default Tables;
You should update your state inside then when the axios call succeeds:
handleSubmit(event) {
event.preventDefault();
axios({...})
.then((response) => {
this.setState({
task_id: response.data.task_id,
submitted: true
})
})
.catch((error) => { /* handle errors appropriately */ })
}
Then, inside your render method, make sure that both task_id and submitted have appropriate values before rendering the modal:
render() {
const { task_id, submitted } = this.state
const modal = submitted && task_id !== ""
? <Example pro="test" task={task_id} />
: null // don't render anything
return (
<div className="table-id">
<Button ...>test</Button>
{modal}
</div>
)
}
This is my code and how can I push the data inside the MuiDataTable of data={data} with my componentDidMount(). I can already fetch the data from my user collection, however, I do not know enough about mui datatable on how to pass it there. This is the one mui datatable -
https://www.material-ui-datatables.com/
import React, {Component} from 'react';
import MUIDataTable from "mui-datatables";
import {firestore} from './../../../firebase/firebase.utils';
const columns = ["Display Name","Email"];
class UserTable extends Component {
state = { user : null}
componentDidMount() {
firestore.collection('users')
.get()
.then( snapshot => {
const users = []
snapshot.forEach(doc => {
const data = doc.data()
users.push(data)
})
this.setState({ users : users})
// console.log(snapshot)
})
.catch(error => console.log(error))
}
render() {
return (
<MUIDataTable
title={"Users"}
columns={columns}
data={data}
// options={options}
/>
);
}
}
export default UserTable;
You need to pass array of object formatted with your column names' as key like {"Display Name": value, Email:other value}.
You need to pass the state into the constructor like:
constructor() {
super();
this.state = { users: [] };
}
And then you just have to pass this.state.usersto MUIDataTable props data, like:
<MUIDataTable
title={"Users"}
columns={this.columns}
data={this.state.users}
// options={options}
/>
For the example I used axios ro fetch data but this work with firestore to:
import MUIDataTable from "mui-datatables";
import { Component } from "react";
import * as axios from "axios";
class UserTable extends Component {
columns = ["Display Name", "Email"];
constructor() {
super();
this.state = { users: [] };
}
componentDidMount() {
axios
.get("/users.json")
.then((res) => {
const userData = res.data.map((u) => {
return {
"Display Name": u.name,
Email: u.email
};
});
console.log(userData);
this.setState({
users: userData
});
})
.catch((error) => console.log(error));
}
render() {
return this.state.users ? (
<MUIDataTable
title={"Users"}
columns={this.columns}
data={this.state.users}
// options={options}
/>
) : (
<div>Loading...</div>
);
}
}
export default UserTable;
With your code this would like :
import MUIDataTable from "mui-datatables";
import { Component } from "react";
import * as axios from "axios";
class UserTable extends Component {
columns = ["Display Name", "Email"];
constructor() {
super();
this.state = { users: [] };
}
componentDidMount() {
firestore.collection('users')
.get()
.then( snapshot => {
const users = []
snapshot.forEach(doc => {
const data = doc.data()
users.push({"Display Name":data.displayName, Email: data.email});
});
return users;})
.then(userList => this.setState({users:userList});
})
.catch(error => console.log(error))
}
render() {
return this.state.users ? (
<MUIDataTable
title={"Users"}
columns={this.columns}
data={this.state.users}
// options={options}
/>
) : (
<div>Loading...</div>
);
}
}
export default UserTable;
UPDATE:
here you can find a working example with firestore
I'm training React Hooks with a movie app and I now face with a problem. When I click in a button in the Header component, there should be a change of state by cleaning the itemsList array. The code is actually prepared for a Load More button, that will add more items to this array, when the API request used with other component (not present yet).
The problem is that the array is not been cleaned and when some button is cliche the items from que API Request are added to it.
This is the App.js file
import React, { useState } from "react";
import axios from "axios";
import Header from "./Containers/Header";
export default function App() {
const [values, setValues] = useState({
msdb: "API_CODE",
page: 1,
totalPages: 0,
listType: "popular",
mode: "movie",
itemsList: [],
searchFiled: "",
loading: false,
error: false
});
const { msdb, page, totalPages, listType, mode, itemsList, searchFiled, loading, error } = values;
const modeSelection = (event) => {
let modeType = "";
let selectedMode = event.target.innerText;
console.log(selectedMode);
if (selectedMode === "Movies") {
modeType = "movie";
} else if (selectedMode === "Series") {
modeType = "tv";
}
setValues((prevValues) => {
return { ...prevValues, mode: modeType, itemsList: [] };
});
let endPoint = `https://api.themoviedb.org/3/${mode}/${listType}?api_key=${msdb}&page=${page}`;
fetchItems(endPoint);
};
const fetchItems = (endPoint) => {
axios
.get(endPoint)
.then((response) => {
const newItemsList = [...itemsList];
const newItems = response.data.results;
if (newItems) {
setValues((prevValues) => {
return {
...prevValues,
page: response.data.page,
itemsList: [...newItemsList, ...newItems],
loading: false,
totalPages: response.data.total_pages
};
});
}
})
.catch((error) => {
setValues({ ...values, error: true });
console.log(error);
});
};
return (
<div className="App">
<Header mode={modeSelection} />
</div>
);
}
And this is the Header.js file
import React from "react";
import "./Header.css";
import { NavLink } from "react-router-dom";
export default function Header(props) {
return (
<div>
<div className="top-center">
<NavLink to="/movies" onClick={props.mode} className="ch-button">
Movies
</NavLink>
<NavLink to="/series" onClick={props.mode} className="ch-button">
Series
</NavLink>
</div>
</div>
);
}
So what I would like to be the result is, when clicking on Header component buttons, the itemsList array should be cleaned and the API request would populate it again. Remember that the axios method is already prepared for a Load More Button in another component and, in this case, it will add more Items to the array. Should there be a useEffect somewhere?
Thank you
The problem is about the asynchronous nature of setState. You correctly use prevState to set a new one, but in the 'fetchItems' when setting new items, you get old ones from current state and not prevState. This way the state is not yet updated with empty array when you use it for setting new items. You can try
if (newItems) {
setValues((prevValues) => {
return {
...prevValues,
page: response.data.page,
itemsList: [...prevState.itemsList, ...newItems],
loading: false,
totalPages: response.data.total_pages
};
});
}
I have the following data loader component in react. It fetches data from API endpoint and renders HTML with that data.
import React, { Component } from "react";
import PropTypes from "prop-types";
class DataLoader extends Component {
static propTypes = {
endpoint: PropTypes.string.isRequired,
render: PropTypes.func.isRequired,
callback: PropTypes.func
};
state = {
data: [],
loaded: false,
placeholder: "Loading..."
};
componentDidMount()
{
fetch(this.props.endpoint)
.then(response => {
if (response.status !== 200) {
return this.setState({ placeholder: "error" });
}
return response.json();
})
.then(data => this.setState({ data: data, loaded: true } ))
.then( this.props.callback );
}
render() {
const { data, loaded, placeholder } = this.state;
return loaded ? this.props.render(data) : <p>{placeholder}</p>;
}
}
export default DataLoader;
Here is App.jsx file
import React from "react";
import ReactDOM from "react-dom";
import DataLoader from "./DataLoader";
import EventDivs from "./EventDivs";
const App = () => (
<DataLoader endpoint="api/v1/calendarevents/"
render={data => <EventDivs data={data} />}
callback = {function() {
console.log($("#renderedDiv").length);
}}
/>
);
const appid = document.getElementById("app");
appid ? ReactDOM.render(<App />, appid ) : null;
console.log($("#renderedDiv").length) gets 0, because this.props.callback is callback of fetch.
I want to know how to call the function after the data that Ajax returned has been rendered?
I have a react, which uses django rest framework API. I'm to get JSON data but it seems I'm not fetching the information correctly or I'm not rendering in the right way:
import React, { Component } from 'react' ;
class App extends Component {
state = {
todos: []
};
async componentDidMount() {
fetch('http://127.0.0.1:8000/api/todos/')
.then(results =>{
console.log(results)
const get_todos = results.map( c=>{
return {
id: c.id,
title: c.title,
descripttion: c.title
};
});
const newstate = Object.assign({},this.state,{
todos: get_todos
});
this.setState(newstate);
}).catch(error=> console.log(error));
}
render(){
return (
<div className="App">
{this.state.todos}
</div>
)
}
}
export default App;
it should be
state = { loading : true }
componentDidMount() {
fetch('http://127.0.0.1:8000/api/todos/')
.then(blob => blob.json())
.then(response => {
...
})
}