簡體   English   中英

使用帶有 graphql 的反應鈎子時,按鈕元素中的 onClick 不會觸發反應表中的重新渲染

[英]onClick in button element not triggering re-render in react-table when using react hooks with graphql

我正在嘗試使用 react-table 呈現表,但是,該表具有從 GraphQL 數據庫中提取的不同狀態。 每個按鈕都應該有效地為表格呈現相同的 UI,但只顯示與用戶單擊的按鈕相關聯的正確狀態的貨件。

我的貨件查詢如下:

import { gql } from 'apollo-boost';

export const GET_SHIPMENTS = gql`
      {
        shipments {
          created_at
          id
          status
          orders {
            order_items
          }
        }
      }
    `;

我使用GET_SHIPMENTS查詢的表組件如下所示:

import React, { useState } from "react";
import { graphql } from 'react-apollo';
import { GET_SHIPMENTS } from '../graphql/ShipmentQueries';
import ReactTable from 'react-table';

import {
  Card,
  CardBody,
  Row,
  ButtonGroup,
  Button
} from "reactstrap";

function OrderTable ({ loading, shipments }) {
  const [shownShipment, setShownShipment] = useState({status: "created"});

  const columns = [
    {
      Header: 'ID',
      accessor: 'id',
    },
    {
      Header: 'Status',
      accessor: 'status',
    },
    {
      Header: 'Item Count',
      accessor: 'orders[0].order_items'
    },
    {
      Header: 'Time Stamp',
      accessor: 'created_at',
    },
  ];

if (loading) return <p>Loading...</p>;
    return (
        <div className="content">
            <ButtonGroup className="center">
                <Button 
                  name="created" 
                  onClick={() => setShownShipment(shownShipment.status === "created")}
                >
                  Created
                </Button>

                <Button 
                  name="awaiting driver" 
                  onClick={() => setShownShipment(shownShipment.status === "awaiting_driver")}
                >
                  Awaiting Driver
                </Button>

                <Button 
                  name="delivered" 
                  onClick={() => setShownShipment(shownShipment.status === "delivered")}
                >
                  Delivered
                </Button>
            </ButtonGroup>
          <Row className="mt-5">
              <Card>
                <CardBody>
                  <ReactTable
                    data={shipments}
                    columns={columns}
                    sortable={true}
                    resizable={false}
                    minRows={10}
                  />
                </CardBody>
              </Card>
          </Row>
        </div>
    );
  }

  export const OrderTableWithData = graphql(GET_SHIPMENTS, {
    props: ({data: { loading, shipments, shownShipments }}) => ({
      loading,
      shipments,
      shownShipments,
    }),
  })(OrderTable);

這是我第一次介紹使用鈎子,所以我知道我可能沒有正確使用它們。 我不確定是否必須使用useEffect掛鈎。 我已經搜索了 Hooks 文檔,但似乎找不到明確的答案。 我覺得useState應該可以工作。 我是否必須重新渲染整個 ReactTable 元素?

如果您希望 shownShipment.status 是與交付狀態相對應的字符串(例如 'delivered'、'awaiting_driver')等,您的 buttonClick 代碼應如下所示:

onClick={() => setShownShipment({status: "delivered"}) }

嘗試像這樣向 react 組件添加效果,以查看單擊每個按鈕后的狀態更新:

useEffect(() => { console.log(shownShipment); }, [shownShipment]);

現在您已將顯示的發貨設置為所需的狀態,您可以根據此過濾來自 GQL 的發貨總列表。 UseState 再次獲取您將實際提供給您的餐桌的貨物清單。 useEffect 在這里也會有所幫助。 像這樣的東西:

// at the top of the component
var [shipmentsToDisplay, setShipmentsToDisplay] = useState([]);

useEffect(() => {
    // loop through all shipments and create a new array for only the ones 
    // you want to show.
    const filteredShipments = 
        shipments && 
            shipments.map(shipment => {
                if (shipment.status === shownShipment) {
                    return shipment;
                }
            }

    setShipmentsToDisplay(filteredShipments);
}, [shownShipment, shipments]);


// Render your table with these shipments rather than props.shipments
<ReactTable
    data={shipmentsToDisplay}
    columns={columns}
    sortable={true}
    resizable={false}
    minRows={10}       
/>

此代碼的解決方案如下:(為簡潔起見,刪除了一些代碼)

function OrderTable ({ loading, shipments }) {
  const [shipmentsToDisplay, setShipmentsToDisplay] = useState([]);

  useEffect(() => {
    if(shipments) {
      filterShipments("created");
    }
  }, [shipments]);

  function filterShipments(status) {
    let shownShipments = [];
    shipments.forEach(element => {
      if(element.status === status) {
        shownShipments.push(element);
      }
    });
    setShipmentsToDisplay(shownShipments);
  }

if (loading) return <Loading />;
    return (
        <div className="content">
            <ButtonGroup className="center">
                <Button name="pending" onClick={() => filterShipments("created")}>
                  Pending
                </Button>
                <Button name="ready" onClick={() => filterShipments("awaiting_driver")}>
                  Ready
                </Button>
                <Button name="completed" onClick={() => filterShipments("delivered")}>
                  Completed
                </Button>
            </ButtonGroup>
          <Row className="mt-5">
            <ReactTable
              data={shipmentsToDisplay}
              columns={columns}
              sortable={true}
              resizable={false}
              defaultPageSize={5}
              className="-striped -highlight"
              getTrProps={getTrProps}
              SubComponent={row => {
                return (
                  <ShipmentDetails
                    shipments={shipments}
                  />
                )
              }}
            />
          </Row>
        </div>
    );
  }

  export const OrderTableWithData = graphql(GET_SHIPMENTS, {
    props: ({data: { loading, shipments }}) => ({
      loading,
      shipments
    }),
  })(OrderTable);

解決方案是登陸Pending shipping,因此對於我的 state,我使用useEffect掛鈎登陸已created為狀態的貨物。

對於我的 onClick function,我決定從created的貨件開始過濾每個貨件,並根據與按鈕單擊關聯的狀態更新 state。 我不知道這是否有意義。 我是鈎子和 GraphQL 的新手。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM