2

我正在尝试通过材料反应表中的 api 获取数据,但它向我显示了一个错误,如下所示 Invalid hook call。钩子只能在函数组件的主体内部调用。这可能是由于以下原因之一: 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);
4

3 回答 3

0

您可以使用以下方式

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

于 2020-01-21T06:34:23.567 回答
0
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 文件中,我已将其放入
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);
            }
        })
}                        

我已将实际表放在名为 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 两次,结果您会看到相同的页面数据

于 2020-04-18T20:19:27.957 回答
0

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

MoviesList

you can not use any hooks inside class based component you need to create functional component for use of

官方文档

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
于 2020-01-21T05:56:53.943 回答