使用带有graphql的react hooks时,按钮元素中的onClick不会触发react-table中的重新渲染
Posted
技术标签:
【中文标题】使用带有graphql的react hooks时,按钮元素中的onClick不会触发react-table中的重新渲染【英文标题】:onClick in button element not triggering re-render in react-table when using react hooks with graphql 【发布时间】:2020-02-24 05:33:54 【问题描述】:我正在尝试使用 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 元素?
【问题讨论】:
当您以这种方式在按钮按下时调用 setShownShipment 时,您将根据当前状态将 shownShipment 设置为 true 或 false。所以,它从“创造”开始,然后变成真或假。这是你的意图吗?我认为您可能正在尝试在交付的按钮按下案例中执行类似 'setShownShipment(status: 'delivered')' 的操作。 我不一定想说状态是真还是假。我想更改状态,从而更新表格的状态,以表明,如果他们单击Delivered
按钮,状态应更新为delivered
,然后渲染表格仅显示已交付的货物。也许在我的钩子里,我应该留下一个空字符串?因为如果我将初始状态设置为 created
然后在我的按钮内,我想我必须做第三个?
您当前运行的 buttonClick 代码仅将显示状态设置为 true 或 false,因为 (shownShipment.status === "created") 仅解析为 true 或 false。请参阅下面的答案。
【参考方案1】:
如果您希望showsShipment.status 为与交货状态对应的字符串(例如'delivered'、'awaiting_driver')等,您的buttonClick 代码应如下所示:
onClick=() => setShownShipment(status: "delivered")
尝试像这样向 react 组件添加一个效果,以查看单击每个按钮后的状态更新:
useEffect(() => console.log(shownShipment); , [shownShipment]);
现在您已将showShipment 设置为所需状态,您可以根据此过滤来自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
/>
【讨论】:
所以我认为这可能是第一步,但是,当我实际单击按钮时,表格不会过滤为 仅 显示那些 交付或你有什么。我想我应该更具体地说明我想要按钮做什么。我最初有一个filterShipments
函数,但不知道如何将它传递给 onClick 处理程序。
在控制台中,我得到了与状态关联的对象,所以看起来是正确的。
检查我的编辑,我想这就是你要找的。span>
我认为这有利于过滤,但由于某种原因,我在setShipmentsToDisplay(filteredShipments)
var setShipmentsToDisplay: (value: React.SetStateAction<any[]>) => void Parsing error: Unexpected token, expected "," 24 | 25 | > 26 | setShipmentsToDisplay(filteredShipments); | ^ 27 | , [shownShipment, shipments]); 28 | 29 |eslint ',' expected.ts(1005)
下收到此错误
所以由于某种原因这仍然无法正常工作,不知道从哪里开始。我必须注释掉它才能显示数据,以便我可以处理其他一些事情。【参考方案2】:
此代码的解决方案如下: (为简洁起见,删除了一些代码)
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
发货开始过滤每个发货,并根据与按钮单击相关联的状态更新状态。我不知道这是否有意义。我是 hooks 和 GraphQL 的新手。
【讨论】:
以上是关于使用带有graphql的react hooks时,按钮元素中的onClick不会触发react-table中的重新渲染的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 React-Hooks 和 Apollo Client 在 React-GraphQL 中实现搜索功能?
使用 React Hook 动态设置 GraphQL 变量不起作用
GraphQL Apollo React Hooks 查询根据初始化顺序返回 null