首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在组件获取数据之前延迟组件的呈现

如何在组件获取数据之前延迟组件的呈现
EN

Stack Overflow用户
提问于 2021-08-02 22:28:01
回答 1查看 102关注 0票数 1

我有一个在ToolkitProvider中具有搜索功能的表组件(如下所示)

当我将搜索属性添加到ToolkitProvider中时,我的reducer会将原始状态作为空对象返回。当我从ToolkitProvider中删除搜索时,我的reducer将返回搜索正常工作所需的对象数组。我在想也许可以有条件地渲染toolkitProvider,但这似乎对我不起作用。有没有办法强制ToolkitProvider等到数据可用后才能使用其搜索功能?我正在使用react-bootstrap-table-next

同样,当search被添加到工具包提供程序时,我的reducer返回一个类似{ group:{}}的空对象,这给了我“数据属于object类型,预期的数组错误”如果我删除search和console.log(groupDetails),它会给我对象数组,表工作正常,添加search get empty object,删除search get array of objects。

下面是我的groupDetails缩减程序

代码语言:javascript
复制
import { GROUP_DETAILS_REQUEST, GROUP_DETAILS_FAIL, GROUP_DETAILS_SUCCESS } from "../actions/types"

export default function groupDetailsReducer ( state = { group: {} }, action ) {
    switch(action.type) {
        case GROUP_DETAILS_REQUEST:
            return { loading: true }
        case GROUP_DETAILS_SUCCESS:
            return action.payload.data.contacts
        case GROUP_DETAILS_FAIL:
            return { loading: false, error: action.payload}
            default:
                return state
    }
}

下面是正在调用的后端userCtrl函数

代码语言:javascript
复制
 const groupById = async (req, res) => {
            
                try {
                    let group = await Group.findById(req.params.id).select('contacts').populate('contacts')
                    if(!group)
                    return res.status(400).json({error: "Group not found"})
         
                    res.json(group)
                    
                } catch(err) {
                    return res.status('400').json({
                        error: 'could not retrieve user'
                    })
                }
            }

下面是使用react-bootstrap-table-next的前端组件

它很大……ToolkitProvider接近底部

代码语言:javascript
复制
import React, { createRef, useEffect, Fragment, useState, Suspense } from 'react';
import {
  Button,
  ButtonGroup,
  Card,
  CardBody,
  Col,
  DropdownItem,
  DropdownMenu,
  DropdownToggle,
  Media,
  Modal,
  ModalBody,
  ModalHeader,
  Row,
  UncontrolledDropdown
} from 'reactstrap';
import FalconCardHeader from '../common/FalconCardHeader';
import ButtonIcon from '../common/ButtonIcon';
import paginationFactory, { PaginationProvider } from 'react-bootstrap-table2-paginator';
import BootstrapTable from 'react-bootstrap-table-next';
import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit';
import { FontAwesomeIcon , faSms} from '@fortawesome/react-fontawesome';
import { useSelector, useDispatch } from 'react-redux';
import { Link } from 'react-router-dom';
import Flex from '../common/Flex';
import Avatar from '../common/Avatar';
import { getPaginationArray } from '../../helpers/utils';

import GroupContactChoose from './GroupContactChoose'
import { deleteGroup, deleteContact, groupById } from '../../actions/index';

const GroupEdit = ({match}) => {


const GroupId = match.params.id
  let table = createRef();
  
  const { SearchBar } = Search;

  const [showContactModal, setShowContactModal ] = useState(false);
  const [isSelected, setIsSelected] = useState(false);
  const dispatch = useDispatch();
   

  const groupDetails = useSelector((state) => state.groupDetails)
  const { success: successGet } = groupDetails


  const CustomTotal = ({ sizePerPage, totalSize, page, lastIndex }) => (
    <span>
      {(page - 1) * sizePerPage + 1} to {lastIndex > totalSize ? totalSize : lastIndex} of {totalSize} —{' '}
    </span>
  );

  const handleDeleteGroup = (_id) => {
   
    if(window.confirm("Are you sure?")) {
  dispatch(deleteGroup(_id))}
  
  }

  const firstNameFormatter = (dataField, {_id, avatar, firstName}) => {
  
    return (
    
      <Link to={`/dashboard/contact/${_id}`}>
        <Media tag={Flex} align="center">
          <Avatar name={firstName} {...avatar} />
          <Media body className="ml-2">
            <h5 className="mb-0 fs--1">{firstName}</h5>
          </Media>
        </Media>
      </Link>
    );
  };
  
  const lastNameFormatter = (dataField, { _id, lastName }) => {
    return (
      <Link to={`/dashboard/contact/${_id}`}>
        <Media tag={Flex} align="center">
          <Media body className="ml-2">
            <h5 className="mb-0 fs--1">{lastName}</h5>
          </Media>
        </Media>
      </Link>
    );
  };

  
  const actionFormatter = (dataField, { _id }, row) => (
    // Control your row with this id
    <UncontrolledDropdown>
      <DropdownMenu right className="border py-2">
        <DropdownItem onClick={() => console.log('Edit: ', _id)}>Edit</DropdownItem> 
        <DropdownItem onClick={() => { handleDeleteGroup(_id)} } className="text-danger">
          Delete
        </DropdownItem>
      </DropdownMenu>
    </UncontrolledDropdown>
  );
  
  

const columns = [
  {
    dataField: 'firstName',
    text: 'First Name',
    headerClasses: 'border-0',
    classes: 'border-0 py-2 align-middle',
    formatter: firstNameFormatter,
    sort: true
  },
 {
   dataField: 'lastName',
   text: 'Last Name',
   headerClasses: 'border-0',
   classes: 'border-0 py-2 align-middle',
   formatter: lastNameFormatter,
   sort: true
 }, 

{
  dataField: 'created',
  headerClasses: 'border-0',
  text: 'Created',
  classes: 'border-0 py-2 align-middle',
  sort: true,
  align: 'right',
  headerAlign: 'right'
},
{
  dataField: 'actions',
  headerClasses: 'border-0',
  text: 'Actions',
  classes: 'border-0 py-2 align-middle',
  formatter: actionFormatter,
  align: 'right'
}
];

const options = {
  custom: true,
  sizePerPage: 12,
  totalSize: groupDetails?.length

  useEffect(() => {
   
    dispatch(groupById(GroupId))   
  }, [successGet])
  
console.log(groupDetails)
  
  return (
    <Card className="mb-3">
      
      <FalconCardHeader title={groupDetails?.group?.data?.title} light={false}>
      
          <Fragment>
            <ButtonGroup className="mt-3">
              <ButtonIcon icon="plus" onClick={() => { setShowContactModal(true)}}transform="shrink-3 down-2" color="falcon-default" size="sm" >
              Add Contacts
            </ButtonIcon>
            <ButtonIcon icon="sms" onClick={() => { console.log(GroupId) }}transform="shrink-3 down-2" color="falcon-default" size="sm" >
              Send SMS
            </ButtonIcon>
            <ButtonIcon icon="edit" onClick={() => { setShowContactModal(true)}}transform="shrink-3 down-2" color="falcon-default" size="sm" >
              Edit
            </ButtonIcon>
            <ButtonIcon icon="trash" onClick={() => { setShowContactModal(true)}}transform="shrink-3 down-2" color="falcon-default" size="sm" >
              Delete
            </ButtonIcon>
            <Modal isOpen={showContactModal} centered toggle={() => setShowContactModal(!showContactModal)}>
            <ModalHeader className="text-center bg-light d-flex flex-between-center border-bottom-0">
                How would you like to Import?
                  </ModalHeader>
                    <ModalBody className="p-0">
                        <Card>
                            <CardBody className="fs--1 font-weight-normal p-4"> 
                                <GroupContactChoose GroupId={GroupId} />
                                <Button block onClick={() => {setShowContactModal(false)}}>Close</Button>
                            </CardBody>
                        </Card>
                    </ModalBody>
                </Modal>
            <ButtonIcon icon="external-link-alt" transform="shrink-3 down-2" color="falcon-default" size="sm">
              Export
            </ButtonIcon>
            </ButtonGroup>
          </Fragment>
        
      </FalconCardHeader>
      <CardBody className="p-0">
    
          {groupDetails.contacts ? (
            <Card>
              <CardBody>
                ...Loading // Attempting conditional rendering and having no luck..
              </CardBody> 
            </Card>
          ) : (

    
     <ToolkitProvider
           keyField="_id"
           columns={columns}
           data={groupDetails}
           bootstrap4
            // search needs to be delayed returning an empty object?
           search <---- when this is added to Toolkit Provider, my reducer returns an empty object  that looks like {group: {}} , this gives me "data is of type object, expected array error" If I remove the search and console.log(groupDetails) It gives me the array of objects and the table works fine, Add search get empty object, remove search get array of objects.
           >
             { props => (
        <PaginationProvider pagination={paginationFactory(options)}>
          {({ paginationProps, paginationTableProps }) => {
            const lastIndex = paginationProps.page * paginationProps.sizePerPage;
            return (
              <Fragment>
                <div className="table-responsive">
                <SearchBar {...props.searchProps} />
                  <BootstrapTable
                    ref={table}
                    selectRow={selectRow(onSelect)}
                    bordered={false}
                    classes="table-dashboard table-striped table-sm fs--1 border-bottom border-200 mb-0 table-dashboard-th-nowrap"
                    rowClasses="btn-reveal-trigger border-top border-200"
                    headerClasses="bg-200 text-900 border-y border-200"
                    {...paginationTableProps}
                    {...props.baseProps}
                  />
        
                </div>
                <Row noGutters className="px-1 py-3 flex-center">
                <Col className="pl-3 fs--1">
                <CustomTotal {...paginationProps} lastIndex={lastIndex} />
              
              </Col>

                  <Col xs="auto">
                    <Button
                      color="falcon-default"
                      size="sm"
                      onClick={handlePrevPage(paginationProps)}
                      disabled={paginationProps.page === 1}
                    >
                      <FontAwesomeIcon icon="chevron-left" />
                    </Button>
                    {getPaginationArray(paginationProps.totalSize, paginationProps.sizePerPage).map(pageNo => (
                      <Button
                        color={paginationProps.page === pageNo ? 'falcon-primary' : 'falcon-default'}
                        size="sm"
                        className="ml-2"
                        onClick={() => paginationProps.onPageChange(pageNo)}
                        key={pageNo}
                      >
                        {pageNo}
                      </Button>
                    ))}
                    <Button
                      color="falcon-default"
                      size="sm"
                      className="ml-2"
                      onClick={handleNextPage(paginationProps)}
                      disabled={lastIndex >= paginationProps.totalSize}
                    >
                      <FontAwesomeIcon icon="chevron-right" />
                    </Button>
                  </Col>
                </Row>
              </Fragment>
            );
          }}
        </PaginationProvider>
         )}
         </ToolkitProvider>
)}
      </CardBody>
      
    </Card>
  )

};

export default GroupEdit
EN

回答 1

Stack Overflow用户

发布于 2021-08-02 22:39:49

听起来你不应该在你的reducer中使用group: {}作为你的默认状态(state = { group: {} })。

一开始你总是会得到默认状态,因为redux会触发一个初始化事件,而这个初始化事件不会影响到你的任何切换情况。

如果您立即加载,这可能是一个很好的初始状态:state = { group: {} }

或者,考虑到错误,也可以使用空数组:state = []

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68628546

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档