0

I got this error when updating state from fetch.

Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

This is my code below

import React  from "react"
import useState from "react"
import {
  Button,
  Progress,
  UncontrolledDropdown,
  DropdownMenu,
  DropdownToggle,
  DropdownItem,
  Input,
Badge,
Row,
Col,
 ListGroup,
  ListGroupItem
} from "reactstrap";
import Draggable from 'react-draggable'
import StatisticsCard from "../../components/@vuexy/statisticsCard/StatisticsCard"
import DataTable from "react-data-table-component"
import classnames from "classnames"
import ReactPaginate from "react-paginate"
import { history } from "../../history"
import {
  Edit,
  Trash,
  ChevronDown,
  Plus,
  Check,
  ChevronLeft,
  ChevronRight,
 Monitor,
  UserCheck,
  Mail,
  Eye,
  MessageSquare,
  ShoppingBag,
  Heart,
  Smile,
  Truck,
  Cpu,
  Server,
  Activity,
  AlertOctagon,
CreditCard,
Share,
Image
} from "react-feather"
import { connect } from "react-redux"
import {
  getData,
  getInitialData,
  deleteData,
  updateData,
  addData,
  filterData
} from "../../redux/actions/data-list/"
import Sidebar from "./DataListSidebar"
import Chip from "../../components/@vuexy/chips/ChipComponent"
import Checkbox from "../../components/@vuexy/checkbox/CheckboxesVuexy"

import "../../assets/scss/plugins/extensions/react-paginate.scss"
import "../../assets/scss/pages/data-list.scss"
import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
import NumberFormat from 'react-number-format';
import $ from 'jquery'
import tc from 'thousands-counter';
 

 

class DataListConfig extends React.Component  {


 constructor(props){
 super(props)
 
 
  this.state = {
    data: [],
    campaigns: [],
    tt: 0,
    totalPages: 0,
    currentPage: 0,
    columns: [
      {
        name: "Name",
        selector: "name",
        sortable: true,
        cell: row => (
          <p title={row.name} className="text-truncate text-bold-500 mb-0">
            {sessionStorage.Name}
          </p>
        )
      },
       {
        name: "Title",
        selector: "title",
        sortable: true,
        cell: row => (
          <p className="text-bold-500 text-truncate mb-0">{row.title}</p>
        )
      },
      
            {
        name: "Total Donation",
        selector: "totaldonor",
        sortable: true,
        cell: row => (
          <p className="text-bold-500 text-truncate mb-0"> <NumberFormat value={row.amounts} displayType={'text'} thousandSeparator={true} prefix={'₦'} /></p>
        )
      },
      {
        name: "Status",
        selector: "status",
        sortable: true,
        cell: row => (
          <Badge
            color={row.status === null || row.status === '' ? "light-danger" : "light-success"}
            pill>
           {row.status === null || row.status === '' ? "Pending":"Active"}
          </Badge>
        )
      },
      
       {
        name: "Start Date",
        selector: "startdate",
        sortable: true,
        cell: row => <p className="text-bold-500 mb-0">{row.startdate}</p>
      },
      {
        name: "Category",
        selector: "category",
        sortable: true,
        cell: row => <p className="text-bold-500 mb-0">{row.category}</p>
      },
      {
        name: "Actions",
        sortable: true,
        cell: row => (
        <this.ActionsComponent
            row={row}
            getData={this.props.getData}
            parsedFilter={this.props.parsedFilter}
            currentData={this.handleCurrentData}
            deleteRow={this.handleDelete}
          />

        )
      }
    ],
    allData: [],
    value: "",
    comments:[],
    rowsPerPage: 4,
    sidebar: false,
    currentData: null,
    selected: [],
    totalRecords: 0,
    sortIndex: [],
    addNew: ""
  }
  const headers = { 'Content-Type': 'application/json' , 'Authorization':`Bearer ${sessionStorage.jwt}`}
    fetch(' ', { headers })
        .then(response => response.json())
        .then(data => {
        
    
   
             
    this.setState({ data: data.posts })
 
}).catch((error) => {
  console.log(error)
});


 }
 
  componentDidMount()
{
 
function ActionsComponent(props) {


        



 
  const {
    buttonLabel,
    className
  } = props;
const [modal, setModal] = useState(false);
const [modal2, setModal2] = useState(false);
  const [items, setItems] = useState([]);
 const [comments,setCom] = useState([])
 
 const Details = (id)=> {
 
 $.post(' ',{
 
 postid: id
 },function(data,status){
  
setItems([
      ...items,
      {
        datas: data
       
      }
    ]);

  
 })
 

  
 }
 

  $.post(' ',{
 
 postid: props.row.id
 },function(data,status){
   
 
this.setState({commets: data})

  
 })
 
 


 
 let datas
 datas = {totaldonors: "",totalcomments:""}
  items.map((key)=>{
 datas = key.datas
  })
 
const dashdata = datas
 


  const toggleModal = (id) =>{ setModal(!modal); };
 const toggleModal2 = (id) =>{ setModal2(!modal2); };
 
  return (
  

  <div>
    <Draggable>
 <Modal
        isOpen={modal}
        toggle={toggleModal}
        className="modal-dialog-centered"
        backdrop={false}
      >
        <ModalHeader toggle={toggleModal}>
          Campaign Dashboard!
        </ModalHeader>
        <ModalBody className="modal-dialog-centered">
  
 <div className="container">
  <div className="row">
    <div className="col-sm">
    <StatisticsCard
              hideChart
              iconBg="primary"
              icon={<CreditCard className="primary" size={22} />}
              stat={tc(dashdata.totaldonors)}
              statTitle="Total Donors"
            />
    </div>
    <div className="col-sm">
    <StatisticsCard
              hideChart
              iconBg="primary"
              icon={<Share className="primary" size={22} />}
              stat="36.9k"
              statTitle="Total Shares"
            />
    </div>
    <div className="col-sm">
    <StatisticsCard
              hideChart
              iconBg="primary"
              icon={<MessageSquare className="primary" size={22} />}
              stat={tc(dashdata.totalcomments)}
              statTitle="Total Comments"
            />
    </div>
<div className="container" style={{'max-height':'300px','overflow-y': 'scroll'}}>

 
</div>
  </div>

</div>


  
        </ModalBody>
        <ModalFooter>
          <Button color="primary">
         Request Withdrawal
          </Button>{" "}
        </ModalFooter>
      </Modal>

                    </Draggable>
                    
                    
                       

    <div className="data-list-action">
    {" "}
    {" "}
      <Edit
        className="cursor-pointer mr-1"
        size={20}
        onClick={() => {
          return props.currentData(props.row)
        }}
      />

 <Activity
        className="cid cursor-pointer mr-1"
        size={20}
          onClick={()=>{return toggleModal(),Details(props.row.id);}}
      />
      
    </div>

</div>

  )

}
 
     
}


  thumbView = this.props.thumbView

 

 

  componentDidUpdate(prevProps, prevState) {
    if (this.thumbView) {
      this.thumbView = false
      let  columns =  [
      {
        name: "Name",
        selector: "name",
        sortable: true,
        cell: row => (
          <p title={row.name} className="text-truncate text-bold-500 mb-0">
            {sessionStorage.Name}
          </p>
        )
      },
       {
        name: "Title",
        selector: "title",
        sortable: true,
        cell: row => (
          <p className="text-bold-500 text-truncate mb-0">{row.title}</p>
        )
      },
      {
        name: "Status",
        selector: "status",
        sortable: true,
        cell: row => (
          <Badge
            color={row.status === null || row.status === '' ? "light-danger" : "light-success"}
            pill>
           {row.status === null || row.status === '' ? "Pending":"Active"}
          </Badge>
        )
      },
            {
        name: "Total Donation",
        selector: "totaldonor",
        sortable: true,
        cell: row => (
          <p className="text-bold-500 text-truncate mb-0">{row.amounts}</p>
        )
      },
      
       {
        name: "Start Date",
        selector: "startdate",
        sortable: true,
        cell: row => <p className="text-bold-500 mb-0">{row.startdate}</p>
      },
      {
        name: "Category",
        selector: "category",
        sortable: true,
        cell: row => <p className="text-bold-500 mb-0">{row.category}</p>
      },
       
      {
          name: "Actions",
          sortable: true,
          cell: row => (
            <this.ActionsComponent
              row={row}
              getData={this.props.getData}
              parsedFilter={this.props.parsedFilter}
              currentData={this.handleCurrentData}
              deleteRow={this.handleDelete}
            />
             
          )
        }
      ]
      this.setState({ columns })
    }
  }

  handleFilter = e => {
    this.setState({ value: e.target.value })
    this.props.filterData(e.target.value)
  }

  handleRowsPerPage = value => {
    let { parsedFilter, getData } = this.props
    let page = parsedFilter.page !== undefined ? parsedFilter.page : 1
    history.push(`/funding/?page=${page}&perPage=${value}`)
    this.setState({ rowsPerPage: value })
    getData({ page: parsedFilter.page, perPage: value })
  }

  handleSidebar = (boolean, addNew = false) => {
    this.setState({ sidebar: boolean })
    if (addNew === true) this.setState({ currentData: null, addNew: true })
  }

  handleDelete = row => {
    this.props.deleteData(row)
    this.props.getData(this.props.parsedFilter)
    if (this.state.data.length - 1 === 0) {
      let urlPrefix = this.props.thumbView
        ? "/funding/"
        : "/funding/"
      history.push(
        `${urlPrefix}list-view?page=${parseInt(
          this.props.parsedFilter.page - 1
        )}&perPage=${this.props.parsedFilter.perPage}`
      )
      this.props.getData({
        page: this.props.parsedFilter.page - 1,
        perPage: this.props.parsedFilter.perPage
      })
    }
  }

  handleCurrentData = obj => {
    this.setState({ currentData: obj })
    this.handleSidebar(true)
  }

  handlePagination = page => {
    let { parsedFilter, getData } = this.props
    let perPage = parsedFilter.perPage !== undefined ? parsedFilter.perPage : 4
 
    let urlPrefix = this.props.thumbView
      ? "/funding/b"
      : "/funding/"
    history.push(
      `${urlPrefix}?page=${page.selected + 1}&perPage=${perPage}`
    )
    getData({ page: page.selected + 1, perPage: perPage })
 
 
    this.setState({ currentPage: page.selected })
  }

  render() {
    let {
      columns,
      data,
      allData,
      totalPages,
      value,
      rowsPerPage,
      currentData,
      sidebar,
      totalRecords,
      sortIndex
    } = this.state
    

    return (
      <div
        className={`data-list ${
          this.props.thumbView ? "thumb-view" : "list-view"
        }`}>
<CustomHeader
handleSidebar={this.handleSidebar}
              handleFilter={this.handleFilter}
              handleRowsPerPage={this.handleRowsPerPage}
              rowsPerPage="5"
              total={totalRecords}
              index={sortIndex}
/>
        <DataTable
          columns={columns}
          data={data}
          pagination

          noHeader
          
          selectableRows
          responsive
          pointerOnHover
          selectableRowsHighlight
          onSelectedRowsChange={data =>
            this.setState({ selected: data.selectedRows })
          }
          customStyles={selectedStyle}
          subHeaderComponent={
            <CustomHeader
              handleSidebar={this.handleSidebar}
              handleFilter={this.handleFilter}
              handleRowsPerPage={this.handleRowsPerPage}
              rowsPerPage="5"
              total={totalRecords}
              index={sortIndex}
            />
          }
          sortIcon={<ChevronDown />}
          selectableRowsComponent={Checkbox}
          selectableRowsComponentProps={{
            color: "primary",
            icon: <Check className="vx-icon" size={12} />,
            label: "",
            size: "sm"
          }}
        />
        <Sidebar
          show={sidebar}
          data={currentData}
          updateData={this.props.updateData}
          addData={this.props.addData}
          handleSidebar={this.handleSidebar}
          thumbView={this.props.thumbView}
          getData={this.props.getData}
          dataParams={this.props.parsedFilter}
          addNew={this.state.addNew}
        />
        <div
          className={classnames("data-list-overlay", {
            show: sidebar
          })}
          onClick={() => this.handleSidebar(false, true)}
        />
      </div>
    )
  }
}

const mapStateToProps = state => {
  return {
    dataList: state.dataList
  }
}

const   handleSidebar = (boolean, addNew = false) => {
    this.setState({ sidebar: boolean })
    if (addNew === true) this.setState({ currentData: null, addNew: true })
  }

export default connect(mapStateToProps, {
  getData,
  deleteData,
  updateData,
  addData,
  getInitialData,
  filterData
})(DataListConfig)

i removed my api endpoint for security purpose

bug image

1 Answers1

0

The DataListConfig component tries to render <this.ActionsComponent>. Because ActionsComponent is defined inside the componentDidMount method, instead of at the class level, this.ActionsComponent is undefined. Which causes the error.

Ultimately though defining a component inside another component is a bad idea. Inside a class component's class as a field, it will mean that each instance of that class component will have their own version of the function component. This smells fishy at best, and is not very React-like.

Move ActionsComponent outside the DataListConfig component entirely, and pass in data it needs through its props.

function ActionsComponent(props) {
  // ...
}

class DataListConfig extends React.Component {
  // ...
}
cbr
  • 12,563
  • 3
  • 38
  • 63
  • how do i set state inside the function, is that possible? – silexsecure lab Jul 02 '20 at 09:58
  • @silexsecurelab You pass a callback function which sets the state in the parent component to the component via props. See the [React tutorial](https://reactjs.org/tutorial/tutorial.html#lifting-state-up) for examples (especially the part where they pass `onClick` to ``) – cbr Jul 02 '20 at 10:00