问题
I am trying to fetch data throught api in material react table but its showing me an error as follows Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM) 2. You might be breaking the Rules of Hooks 3. You might have more than one copy of React in the same app
code is mentioned below:
import React, { Component } from 'react';
import MaterialTable from "material-table";
import withStyles from "@material-ui/core/styles/withStyles";
import { makeStyles } from '@material-ui/core/styles';
import ReactTable from 'react-table'
import api from '../../api'
import { Button } from 'react-floating-action-button'
import "@fortawesome/fontawesome-free/css/all.min.css";
import "bootstrap-css-only/css/bootstrap.min.css";
import "mdbreact/dist/css/mdb.css";
import {
MDBBtn,
} from "mdbreact";
import "react-table/react-table.css";
import styled from 'styled-components'
import 'react-table/react-table.css'
import { whiteColor } from 'assets/jss/material-dashboard-react';
import { createSourceConfiguration } from '../../components/UserForm/SourceDatasetSelection';
import { grayColor } from 'assets/jss/material-dashboard-react';
const styles = {
cardCategoryWhite: {
color: "rgba(255,255,255,.62)",
margin: "0",
fontSize: "14px",
marginTop: "0",
marginBottom: "0"
},
cardTitleWhite: {
color: "#FFFFFF",
marginTop: "0px",
minHeight: "auto",
fontWeight: "300",
fontFamily: "'Roboto', 'Helvetica', 'Arial', sans-serif",
marginBottom: "3px",
textDecoration: "none"
}
};
class MoviesList extends Component {
constructor(props) {
super(props)
this.state = {
movies: [],
columns: [],
isLoading: true,
}
}
componentDidMount = async () => {
this.setState({ isLoading: true })
await api.getAllMovies().then(movies => {
this.setState({
movies: movies.data.data,
isLoading: false,
})
})
}
render() {
const { movies, isLoading } = this.state
console.log('TCL: Configuration List -> render -> movies', movies)
// const { movies, isLoading } = this.state
const [state, setState] = React.useState({
columns: [
{
title: "Dataset Name",
// field: "dataset",
accessor: 'configname',
// type: "String",
headerStyle: { fontSize: 20,backgroundColor:grayColor},
cellStyle: {fontSize: 18},
}
]
});
return (
<div style={{ maxWidth: "100%" }}>
<MaterialTable
title=''
columns={state.columns}
data={state.data}
editable={{
onRowAdd: newData =>
new Promise(resolve => {
setTimeout(() => {
resolve();
const data = [...state.data];
data.push(newData);
setState({ ...state, data });
}, 600);
}),
onRowUpdate: (newData, oldData) =>
new Promise(resolve => {
setTimeout(() => {
resolve();
const data = [...state.data];
data[data.indexOf(oldData)] = newData;
setState({ ...state, data });
}, 600);
}),
onRowDelete: oldData =>
new Promise(resolve => {
setTimeout(() => {
resolve();
const data = [...state.data];
data.splice(data.indexOf(oldData), 1);
setState({ ...state, data });
}, 600);
})
}}
/>
</div>
);
}
}
export default MoviesList
//export default withStyles(styles)(Dataset);
回答1:
This error shows that you are trying to access hooks inside your class component :
MoviesList
you can not use any hooks inside class based component you need to create functional component for use of
Official doc
import React , { useState, useEffect } from 'react';
class MoviesList = () => {
const [movies,setMovies] = useState([]);
const [columns,setColumns] = useState([]);
const [isLoading,setIsLoading] = useState(false);
useEffect(async ()=> {
setIsLoading(true)
await api.getAllMovies().then(movies => {
setMovies(movies.data.data);
setIsLoading(false);
})
} , [])
.... your logic
}
export default MoviesList
回答2:
You can use the following ways
1) import useEffect for hooks
import React , { useState, useEffect } from 'react';
2) use the following way
useEffect(async()=>{ code... },[]);
this code act on componentDidMount
you can use the conditions inside Square brackets '[]'
like as any change data from the list
useEffect(async()=>{
// check the onother variable is updated or not
},[list]);
You learn more about React hooks here: React Doc
回答3:
import React, { Component, useState, useMemo } from 'react';
import Table, { StylesSimple, SelectColumnFilter, NumberRangeColumnFilter } from
'../Tables/TableSimple';
import {GetCompanyRequesteddata } from '../APICalls/dbCompany';
var config = { "Access-Control-Allow-Origin": "*" }
export class CompanySearch extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: false,
requestedData: [],
totalPageCount: 0,
defaultPageSize: 10,
pagereset: false,
};
fetchData = (state, instance) => {
this.setState({ isLoading: true });
const pasdata = {
pageIndex: state.pageIndex,
pageSize: state.pageSize,
};
GetCompanyRequesteddata(config, pasdata, (res) => {
this.setState({ requestedData: res.data.basicCompanyDataList, isLoading: false, defaultPageSize: state.pageSize, totalPageCount: res.data.totalPageCount, pageIndex: state.pageIndex });
},
(err) => {
});
}
render() {
return (
//you may have other components here
<div className="container-fluid">
<StylesSimple>
<Table
data={this.state.requestedData || []}
columns={columns}
onFetchData={this.fetchData}
loading={this.state.isLoading}
pageCount={this.state.totalPageCount}
skipPageReset={this.state.pageReset}
/>
</StylesSimple>
</div>
</div>
</div>
</div >);
}
} }
const columns = [
{
Header: 'RowId',
accessor: (row, i) => i + 1,
width: 150,
maxWidth: 150,
minWidth: 150
},
{
Header: 'Company',
columns: [
{
Header: 'Name',
accessor: 'companyName',
aggregate: 'count',
Aggregated: ({ cell: { value } }) => `${value} Names`,
width: 250,
maxWidth: 250,
minWidth: 250
},
{
Header: 'Number',
accessor: 'companyNumber',
// Use our custom `fuzzyText` filter on this column
filter: 'fuzzyText',
// Use another two-stage aggregator here to
// first count the UNIQUE values from the rows
// being aggregated, then sum those counts if
// they are aggregated further
aggregate: 'uniqueCount',
Aggregated: ({ cell: { value } }) => `${value} Unique Names`,
width: 150,
minWidth: 100,
maxWidth: 400,
},
],
},],
web api call in separate javascript file which i have placed in
import {GetCompanyRequesteddata } from '../APICalls/dbCompany';
export async function GetCompanyRequesteddata(config, payload, callback, errorcallback) {
await axios({
method: 'post',
url: 'api/v1/companydata/GetCompanyRequestedData',
data: JSON.stringify(payload),
headers: {
'secret-key': 'your secret key',
'Content-Type': 'application/json'
}
})
.then(res => {
if (callback !== null) {
callback(res)
}
}).catch(err => {
if (errorcallback !== null) {
errorcallback(err);
}
})
}
actual table I have placed in separate javascript file called TableSimple and exported as functional component
function Table({ columns, data, onFetchData, loading, pageCount: controlledPageCount, skipPageReset }) {
const [filterInput, setFilterInput] = useState('');
const filterTypes = React.useMemo(
() => ({
// Add a new fuzzyTextFilterFn filter type.
fuzzyText: fuzzyTextFilterFn,
// Or, override the default text filter to use
// "startWith"
text: (rows, id, filterValue) => {
return rows.filter(row => {
const rowValue = row.values[id]
return rowValue !== undefined
? String(rowValue)
.toLowerCase()
.startsWith(String(filterValue).toLowerCase())
: true
})
},
}),
[]
)
const defaultColumn = React.useMemo(
() => ({
// Let's set up our default Filter UI
Filter: DefaultColumnFilter,
minWidth: 30,
width: 50,
maxWidth: 400,
}),
[]
)
const {
getTableProps,
getTableBodyProps,
headerGroups,
prepareRow,
page,
canPreviousPage,
canNextPage,
pageOptions,
pageCount,
gotoPage,
nextPage,
previousPage,
setPageSize,
state: { pageIndex, pageSize },
} = useTable(
{
columns,
data,
initialState: { pageIndex: 0 },
manualPagination: true,
pageCount: controlledPageCount,
defaultColumn,
filterTypes,
disableMultiSort: true,
***autoResetPage: skipPageReset,***
},
useFilters,
useGroupBy,
useSortBy,
useExpanded,
most important issue to be remember for server side data fetch is autoResetPage: skipPageReset
if you don't manage it by controlling {this.state.pageReset} it may call the fetchData twice as a result you would see same page data
来源:https://stackoverflow.com/questions/59834837/not-able-to-fetch-data-through-api-in-material-table-react