gpt4 book ai didi

reactjs - 乐观的 React Apollo ui 滞后与 React 美丽的拖放

转载 作者:行者123 更新时间:2023-12-03 13:43:49 25 4
gpt4 key购买 nike

我正在尝试创建一个乐观的响应,其中用户界面通过拖放数据立即更新(最小的延迟和更好的用户体验)。然而,我遇到的问题是它无论如何都会滞后。

所以发生的情况是,我期望从查询中获得区域和未分配区域的列表,unassignedZone 是一个对象,其中包含城市,区域是其中包含城市的区域列表。在编写我的突变时,我在拖放它们后返回新的重新排序的区域列表。重新排序是通过区域对象上名为“DisplayOrder”的字段完成的。逻辑正在正确设置数字。问题是,当我尝试用乐观的 ui 和更新来模仿它时,会出现轻微的延迟,就像它仍在等待网络一样。

我想要实现的大部分内容都发生在 onDragEnd = () => { ... } 函数中。

import React, { Component } from "react";
import { graphql, compose, withApollo } from "react-apollo";
import gql from "graphql-tag";
import { withState } from "recompose";
import { withStyles } from "@material-ui/core/styles";
import Select from "@material-ui/core/Select";
import MenuItem from "@material-ui/core/MenuItem";
import Input from "@material-ui/core/Input";
import Grid from "@material-ui/core/Grid";
import InputLabel from "@material-ui/core/InputLabel";
import Tabs from "@material-ui/core/Tabs";
import Tab from "@material-ui/core/Tab";
import AppBar from "@material-ui/core/AppBar";
import _ from "lodash";
import FormControl from "@material-ui/core/FormControl";
import move from "lodash-move";
import { Zone } from "../../Components/Zone";

const style = {
ddlRight: {
left: "3px",
position: "relative",
paddingRight: "10px"
},
ddlDrop: {
marginBottom: "20px"
},
dropdownInput: {
minWidth: "190px"
}
};

class Zones extends Component {
constructor(props) {
super(props);
this.state = {
companyId: "",
districtId: "",
selectedTab: "Zones",
autoFocusDataId: null,
zones: [],
unassignedZone: null
};
}

handleChange = event => {
const { client } = this.props;
this.setState({ [event.target.name]: event.target.value });
};

handleTabChange = (event, selectedTab) => {
this.setState({ selectedTab });
};

onDragStart = () => {
this.setState({
autoFocusDataId: null
});
};

calculateLatestDisplayOrder = () => {
const { allZones } = this.state;
if (allZones.length === 0) {
return 10;
}
return allZones[allZones.length - 1].displayOrder + 10;
};

updateCitiesDisplayOrder = cities => {
let displayOrder = 0;
const reorderedCities = _.map(cities, aCity => {
displayOrder += 10;
const city = { ...aCity, ...{ displayOrder } };
if (city.ZonesCities) {
city.ZonesCities.displayOrder = displayOrder;
}
return city;
});
return reorderedCities;
};

moveAndUpdateDisplayOrder = (allZones, result) => {
const reorderedZones = _.cloneDeep(
move(allZones, result.source.index, result.destination.index)
);
let displayOrder = 0;
_.each(reorderedZones, (aZone, index) => {
displayOrder += 10;
aZone.displayOrder = displayOrder;
});
return reorderedZones;
};

/**
* droppable id board represents zones
* @param result [holds our source and destination draggable content]
* @return
*/

onDragEnd = result => {
console.log("Dragging");
if (!result.destination) {
return;
}
const source = result.source;
const destination = result.destination;
if (
source.droppableId === destination.droppableId &&
source.index === destination.index
) {
return;
}

const {
zonesByCompanyAndDistrict,
unassignedZoneByCompanyAndDistrict
} = this.props.zones;
// reordering column
if (result.type === "COLUMN") {
if (result.source.index < 0 || result.destination.index < 0) {
return;
}

const { reorderZones, companyId, districtId } = this.props;
const sourceData = zonesByCompanyAndDistrict[result.source.index];
const destinationData =
zonesByCompanyAndDistrict[result.destination.index];
const reorderedZones = this.moveAndUpdateDisplayOrder(
zonesByCompanyAndDistrict,
result
);
console.log(reorderedZones);
console.log(unassignedZoneByCompanyAndDistrict);
reorderZones({
variables: {
companyId,
districtId,
sourceDisplayOrder: sourceData.displayOrder,
destinationDisplayOrder: destinationData.displayOrder,
zoneId: sourceData.id
},
optimisticResponse: {
__typename: "Mutation",
reorderZones: {
zonesByCompanyAndDistrict: reorderedZones
}
},
// refetchQueries: () => ["zones"],
update: (store, { data: { reorderZones } }) => {
const data = store.readQuery({
query: unassignedAndZonesQuery,
variables: {
companyId,
districtId
}
});

store.writeQuery({
query: unassignedAndZonesQuery,
data: data
});
}
});
// this.setState({ zones: reorderedZones });
// Need to reorder zones api call here
// TODO: Elixir endpoint to reorder zones
}
return;
};

render() {
const { selectedTab } = this.state;
const {
classes,
companies,
districts,
companyId,
districtId,
setCompanyId,
setDistrictId,
zones
} = this.props;
const isDisabled = !companyId || !districtId;
return (
<Grid container spacing={16}>
<Grid container spacing={16} className={classes.ddlDrop}>
<Grid item xs={12} className={classes.ddlRight}>
<h2>Company Zones</h2>
</Grid>
<Grid item xs={2} className={classes.ddlRight}>
<FormControl>
<InputLabel htmlFor="company-helper">Company</InputLabel>
<Select
value={companyId}
onChange={event => {
setCompanyId(event.target.value);
}}
input={
<Input
name="companyId"
id="company-helper"
className={classes.dropdownInput}
/>
}
>
{_.map(companies.companies, aCompany => {
return (
<MenuItem
value={aCompany.id}
key={`companyItem-${aCompany.id}`}
>
{aCompany.name}
</MenuItem>
);
})}
</Select>
</FormControl>
</Grid>
<Grid item xs={2} className={classes.ddlRight}>
<FormControl>
<InputLabel htmlFor="district-helper">District</InputLabel>
<Select
value={districtId}
onChange={event => {
setDistrictId(event.target.value);
}}
input={
<Input
name="districtId"
id="district-helper"
className={classes.dropdownInput}
/>
}
>
{_.map(districts.districts, aDistrict => {
return (
<MenuItem
value={aDistrict.id}
key={`districtItem-${aDistrict.id}`}
>
{aDistrict.name}
</MenuItem>
);
})}
</Select>
</FormControl>
</Grid>
</Grid>
<Grid container>
<AppBar position="static" color="primary">
<Tabs value={selectedTab} onChange={this.handleTabChange}>
<Tab value="Zones" label="Zone" disabled={isDisabled} />
<Tab
value="Pricing Structure"
label="Pricing Structure"
disabled={isDisabled}
/>
<Tab value="Pricing" label="Pricing" disabled={isDisabled} />
<Tab
value="Student Pricing"
label="Student Pricing"
disabled={isDisabled}
/>
</Tabs>
</AppBar>
{selectedTab === "Zones" &&
zones &&
zones.zonesByCompanyAndDistrict && (
<Zone
onDragStart={this.onDragStart}
onDragEnd={this.onDragEnd}
zones={_.sortBy(zones.zonesByCompanyAndDistrict, [
"displayOrder"
])}
unassignedZone={zones.unassignedZoneByCompanyAndDistrict}
/>
)}
{selectedTab === "Pricing Structure" && <div>Pricing Structure</div>}
{selectedTab === "Pricing" && <div>Pricing</div>}
{selectedTab === "Student Pricing" && <div>Student Pricing</div>}
</Grid>
</Grid>
);
}
}

const companiesQuery = gql`
query allCompanies {
companies {
id
name
}
}
`;

const districtsQuery = gql`
query allDistricts {
districts {
id
name
}
}
`;

const unassignedAndZonesQuery = gql`
query zones($companyId: String!, $districtId: String!) {
unassignedZoneByCompanyAndDistrict(
companyId: $companyId
districtId: $districtId
) {
name
description
displayOrder
cities {
id
name
}
}

zonesByCompanyAndDistrict(companyId: $companyId, districtId: $districtId) {
id
name
description
displayOrder
basePrice
zoneCities {
displayOrder
city {
id
name
}
}
}
}
`;

const reorderZones = gql`
mutation(
$companyId: String!
$districtId: String!
$sourceDisplayOrder: Int!
$destinationDisplayOrder: Int!
$zoneId: String!
) {
reorderZones(
companyId: $companyId
districtId: $districtId
sourceDisplayOrder: $sourceDisplayOrder
destinationDisplayOrder: $destinationDisplayOrder
zoneId: $zoneId
) {
id
__typename
name
description
displayOrder
basePrice
zoneCities {
displayOrder
city {
id
name
}
}
}
}
`;

export default compose(
withState("companyId", "setCompanyId", ""),
withState("districtId", "setDistrictId", ""),
graphql(unassignedAndZonesQuery, {
name: "zones",
skip: ({ companyId, districtId }) => !(companyId && districtId),
options: ({ companyId, districtId }) => ({
variables: { companyId, districtId },
fetchPolicy: "cache-and-network"
})
}),
graphql(companiesQuery, {
name: "companies",
options: { fetchPolicy: "cache-and-network" }
}),
graphql(districtsQuery, {
name: "districts",
options: { fetchPolicy: "cache-and-network" }
}),
graphql(reorderZones, {
name: "reorderZones"
}),
withApollo,
withStyles(style)
)(Zones);

https://drive.google.com/file/d/1ujxTOGr0YopeBxrGfKDGfd1Cl0HiMaK0/view?usp=sharing <- 这是一个演示它发生的视频。

最佳答案

对于遇到同样问题的任何人来说,主要问题是我的 update/optimisticResponse 都不正确。这里值得一提的是这个 block :

update: (store, { data: { reorderZones } }) => {
const {
zonesByCompanyAndDistrict,
unassignedZoneByCompanyAndDistrict
} = store.readQuery({
query: unassignedAndZonesQuery,
variables: {
companyId,
districtId
}
});
const reorderedZones = this.moveAndUpdateDisplayOrder(
zonesByCompanyAndDistrict,
result
);
store.writeQuery({
query: unassignedAndZonesQuery,
variables: { companyId, districtId },
data: {
unassignedZoneByCompanyAndDistrict,
zonesByCompanyAndDistrict: reorderedZones
}
});
}

如果你将它与我上面的原始代码进行比较,你会发现当我 writeQuery 时我这次有变量。查看 apollo devtools,我发现添加了一个条目,只是一个变量错误。所以这是一个简单的修复。乐观的响应是正确的(模仿从我们的突变返回的有效负载)。另一个错误的方面是,我获取所有这些数据的查询最初有缓存和网络的获取策略,这意味着当我们收到数据时,我们会缓存它,并请求最新的数据。所以这将始终获取最新数据。我不需要那个,因此会出现一点延迟,我只需要乐观响应。默认情况下,apollo 执行缓存优先,它在缓存中查找数据,如果不存在,我们通过网络获取它。与缓存更新和慢速网络完美搭配。

关于reactjs - 乐观的 React Apollo ui 滞后与 React 美丽的拖放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52360171/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com