onClick в элементе кнопки, не вызывающем повторную визуализацию в реагирующей таблице при использовании перехватчиков реакции с graphql - PullRequest
0 голосов
/ 29 октября 2019

Я пытаюсь отобразить таблицу, используя реагирующую таблицу, однако эта таблица имеет различные состояния, которые извлекаются из базы данных GraphQL. Каждая кнопка должна эффективно отображать один и тот же пользовательский интерфейс для таблицы, но отображать только те отгрузки, которые имеют правильный статус, связанный с тем, на какую кнопку нажал пользователь.

Мой запрос на отправку выглядит следующим образом:

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 крючок или нет. Я просмотрел документы Крюка и не могу найти четкого ответа. Я чувствую, что useState должно работать. Нужно ли повторно визуализировать весь элемент ReactTable?

Ответы [ 2 ]

0 голосов
/ 31 октября 2019

Решение для этого кода было следующим: (Некоторый код был удален для краткости)

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, поэтому для моего штата я использовал useEffect подключиться к посылкам, которые имеют статус created.

Для функции onClick я решил отфильтровать каждую отправку, начиная с отправлений created, и обновить состояние в зависимости от того, какой статуссвязанный с нажатием кнопки. Я не знаю, имеет ли это смысл или нет. Я новичок в хуках и GraphQL.

0 голосов
/ 29 октября 2019

Если вы хотите, чтобы в свойствах selectedShipment.status была строка, соответствующая статусу доставки (например, «доставлено», «ожидание_драйвера») и т. Д., Ваш код buttonClick должен выглядеть следующим образом:

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

Попробуйте добавитьэффект на компонент реагирования, подобный этому, чтобы увидеть обновление статуса после нажатия каждой кнопки:

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

Теперь, когда вы установили для Shipment установленный желаемый статус, вы можете отфильтровать ваш общий список отправлений на основе GQL. на этом. Снова используйтеState для списка отправлений, которые вы фактически дадите на свой стол. 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}       
/>
...