如何使用 Apollo graphql 实现 react-sortable-hoc?
Posted
技术标签:
【中文标题】如何使用 Apollo graphql 实现 react-sortable-hoc?【英文标题】:How to implement react-sortable-hoc with Apollo graphql? 【发布时间】:2020-08-20 23:01:19 【问题描述】:Link with sample gif of issue here!
您好,我正在创建一个允许用户创建列表的应用程序(所有数据都存储在 mongoDB 上并通过 Apollo GraphQL 访问);每个列表都有一个属性 listItems,这是一个存储列表中所有项目的数组。
当用户进入个人 Ranklist.js 组件页面时,它会加载列表,其中包含通过 graphQL 查询访问的所有列表项。
从这里开始,应用程序利用react-sortable-hoc 允许用户移动列表项。虽然我可以移动 listItems,但只要我放手,页面就会重置顺序以匹配存储在 mongoDB 上的数组的顺序。
请告诉我为什么会出现这种情况,以及我如何正确实施一种方法,通过 Apollo graphQL 与数据库一起使用 react-sortable-hoc 保存列表的顺序。
import React, useContext, useRef, useState from "react";
import gql from "graphql-tag";
import useQuery, useMutation from "@apollo/react-hooks";
import
Form,
from "semantic-ui-react";
import moment from "moment";
import AuthContext from "../context/auth";
import SortableContainer, SortableElement from "react-sortable-hoc";
import arrayMove from "array-move";
import "../RankList.css";
import CSSTransitionGroup from "react-transition-group";
const SortableItem = SortableElement(( value ) => (
<li className="listLI">value</li>
));
const SortableList = SortableContainer(( items ) =>
return (
<ol className="theList">
<CSSTransitionGroup
transitionName="ranklist"
transitionEnterTimeout=500
transitionLeaveTimeout=300
>
items.map((item, index) => (
<SortableItem
key=`item-$item.id`
index=index
value=item.body
/>
))
</CSSTransitionGroup>
</ol>
);
);
function RankList(props)
const listId = props.match.params.listId;
const user = useContext(AuthContext);
const listItemInputRef = useRef(null);
const [state, setState] = useState( items: [] );
const [listItem, setListItem] = useState("");
const loading, error, data = useQuery(FETCH_LIST_QUERY,
variables:
listId,
,
);
const [submitListItem] = useMutation(SUBMIT_LIST_ITEM_MUTATION,
update()
setListItem("");
listItemInputRef.current.blur();
,
variables:
listId,
body: listItem,
,
);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error..</p>;
function deleteListCallback()
props.history.push("/");
function onSortEnd( oldIndex, newIndex )
setState(( items ) => (
items: arrayMove(items, oldIndex, newIndex),
));
let listMarkup;
if (!data.getList)
listMarkup = <p>Loading list...</p>;
else
const
id,
title,
createdAt,
username,
listItems,
comments,
likes,
likeCount,
commentCount,
= data.getList;
listMarkup = user ? (
<div className="todoListMain">
<div className="rankListMain">
<div className="rankItemInput">
<h3>title</h3>
<Form>
<div className="ui action input fluid">
<input
type="text"
placeholder="Choose rank item.."
name="listItem"
value=listItem
onChange=(event) => setListItem(event.target.value)
ref=listItemInputRef
/>
<button
type="submit"
className="ui button teal"
disabled=listItem.trim() === ""
onClick=submitListItem
>
Submit
</button>
</div>
</Form>
</div>
<SortableList
items=listItems
onSortEnd=onSortEnd
helperClass="helperLI"
/>
</div>
</div>
) : (
<div className="todoListMain">
<div className="rankListMain">
<div className="rankItemInput">
<h3>props.title</h3>
</div>
<SortableList
items=listItems
onSortEnd=onSortEnd
helperClass="helperLI"
/>
</div>
</div>
);
return listMarkup;
const SUBMIT_LIST_ITEM_MUTATION = gql`
mutation($listId: ID!, $body: String!)
createListItem(listId: $listId, body: $body)
id
listItems
id
body
createdAt
username
comments
id
body
createdAt
username
commentCount
`;
const FETCH_LIST_QUERY = gql`
query($listId: ID!)
getList(listId: $listId)
id
title
createdAt
username
listItems
id
createdAt
username
body
likeCount
likes
username
commentCount
comments
id
username
createdAt
body
`;
export default RankList;
【问题讨论】:
【参考方案1】:您的onSortEnd
函数调用setState
并相应地更新state.items
,但是您永远不会在组件中使用state.items
——而是直接使用data.getList.listItems
。由于该值在最初获取后不会更改,因此您的列表保持不变。
您应该改用state.items
。然后,您可以在listItems
的值发生变化时使用useEffect
更新state.items
——例如,最初是在返回来自服务器的响应或响应突变时。比如:
onEffect(() =>
if (data && data.getList && data.getList.listItems)
setState(() => ( items: data.getList.listItems ))
, [data])
【讨论】:
非常感谢您的回复。我对此很陌生,你会建议我把onEffect放在哪里?另外,当我最初加载这个组件时,我将如何给出 state.items 的值,我的 mongoDB 中的所有 listItems (有没有办法插入它在这种情况下最初是通过 setState 吗?)由于某种原因,我在尝试以下操作时收到“数据未定义”: const loading, error, data = useQuery(FETCH_LIST_QUERY, variables: listId, , ); const [state, setState] = useState( items: data.getList.listItems );data
最初是未定义的,因为获取查询是异步的。像您目前正在做的那样,将 items
初始化为一个空数组。在声明其他钩子后放置useEffect
。因为我们将[data]
作为第二个参数传递给useEffect
,所以我们作为第一个参数传入的函数将在每次数据变化时被调用。见here。以上是关于如何使用 Apollo graphql 实现 react-sortable-hoc?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 NestJS GraphQL 实现 NuxtJS Apollo
如何使用 apollo ios 客户端实现 graphql 订阅
如何使“apollo 服务器”与 graphql schemaObject 一起使用?
如何使用 Apollo graphql 实现 react-sortable-hoc?