【问题标题】:not able to fetch data through api in material table react无法通过材料表中的api获取数据反应
【发布时间】:2020-05-07 03:27:57
【问题描述】:

我正在尝试通过材料反应表中的 api 获取数据,但它向我显示如下错误 无效的挂钩调用。 Hooks 只能在函数组件的主体内部调用。这可能由于以下原因之一而发生: 1. React 和渲染器的版本可能不匹配(例如 React DOM) 2. 你可能违反了 Hooks 的规则 3. 你可能在同一个应用中拥有多个 React 副本

代码如下:

    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);

【问题讨论】:

    标签: javascript reactjs material-table mdbreact


    【解决方案1】:

    此错误表明您正在尝试访问类组件中的钩子:

    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】:

      您可以使用以下方式

      1) 为钩子导入 useEffect

      import React , { useState, useEffect } from 'react';
      

      2) 使用如下方式

      useEffect(async()=>{ code... },[]); 
      

      此代码作用于 componentDidMount

      您可以使用方括号'[]'内的条件

      就像列表中的任何更改数据一样

      useEffect(async()=>{
         // check the onother variable is updated or not
      },[list]);
      

      您可以在此处了解有关 React 钩子的更多信息: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 调用在我放置的单独的 javascript 文件中
        从 '../APICalls/dbCompany' 导入 {GetCompanyRequesteddata };

        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);
                    }
                })
        }                        
        

        我已将实际表放在名为 TableSimple 的单独 javascript 文件中并导出为功能组件

        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, 
        

        服务器端数据获取最重要的问题是 autoResetPage: skipPageReset

        如果你不通过控制 {this.state.pageReset} 来管理它,它可能会调用 fetchData 两次,结果你会看到相同的页面数据

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-09-04
          • 2019-05-14
          • 2020-10-08
          • 2022-06-30
          • 2020-10-26
          • 1970-01-01
          • 1970-01-01
          • 2021-11-30
          相关资源
          最近更新 更多