问题太多...简要:
我正在创建一个允许用户创建列表的应用程序(所有数据都存储在mongoDB上,并可以通过Apollo GraphQL访问);每个列表都有一个属性listItems,该数组存储列表中的所有项目。
目前,我现在可以移动listItem并通过state.items访问数组中的setState,如in this video所示。
我遇到的问题是采用listItems的state.items数组,并使用一种变异使state.items数组替换数据库中各自的后端list.listItems数组。
我相信我可能没有正确设置输入ListItems的typeDefs(我得到了错误:Mutation.editListItems(listItems :)的类型必须是Input Type,但得到了:[ListItem]!。]。>输入而不是可能是问题的类型?)
最后,我尝试在下面的RankList功能组件(包含在RankList.js中)中将editListItems突变称为“ onChange”。我不确定问题出在哪里以及在移动物品时,似乎没有调用该突变。请告知(让我知道是否应提供更多信息)!
总体上,我想知道是否可能是以下问题:
typeDefs.jsconst { gql } = require("apollo-server");
//schema
module.exports = gql`
type List {
id: ID!
title: String!
createdAt: String!
username: String!
listItems: [ListItem]!
comments: [Comment]!
likes: [Like]!
likeCount: Int!
commentCount: Int!
}
type ListItem {
id: ID!
createdAt: String!
username: String!
body: String!
}
input ListItems {
id: ID!
createdAt: String!
username: String!
body: String!
}
type Comment {
id: ID!
createdAt: String!
username: String!
body: String!
}
type Like {
id: ID!
createdAt: String!
username: String!
}
type User {
id: ID!
email: String!
token: String!
username: String!
createdAt: String!
}
input RegisterInput {
username: String!
password: String!
confirmPassword: String!
email: String!
}
type Query {
getLists: [List]
getList(listId: ID!): List
}
type Mutation {
register(registerInput: RegisterInput): User!
login(username: String!, password: String!): User!
createList(title: String!): List!
editListItems(listId: ID!, listItems: [ListItems]!): List!
deleteList(listId: ID!): String!
createListItem(listId: ID!, body: String!): List!
deleteListItem(listId: ID!, listItemId: ID!): List!
createComment(listId: ID!, body: String!): List!
deleteComment(listId: ID!, commentId: ID!): List!
likeList(listId: ID!): List!
},
type Subscription{
newList: List!
}
`;
list.js(解析器)
async editListItems(_, { listId, listItems }, context) {
console.log("editListItems Mutation activated!");
const user = checkAuth(context);
const list = await List.findById(listId);
if (list) {
if (user.username === list.username) {
list.listItems = listItems;
await list.save();
return list;
} else {
throw new AuthenticationError("Action not allowed");
}
} else {
throw new UserInputError("List not found");
}
},
RankList.js(上面的视频中显示了列表组件)
import React, { useContext, useEffect, 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,
},
});
useEffect(() => {
if (data && data.getList && data.getList.listItems) {
setState(() => ({ items: data.getList.listItems }));
}
}, [data]);
// const [state, setState] = useState({ items: data.getList.listItems });
const [submitListItem] = useMutation(SUBMIT_LIST_ITEM_MUTATION, {
update() {
setListItem("");
listItemInputRef.current.blur();
},
variables: {
listId,
body: listItem,
},
});
const [editListItems] = useMutation(EDIT_LIST_ITEMS_MUTATION, {
variables: {
listId,
listItems: state.items,
},
});
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={state.items}
onSortEnd={onSortEnd}
onChange={editListItems}
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 EDIT_LIST_ITEMS_MUTATION = gql`
mutation($listId: ID!, $listItems: [ListItems]!) {
editListItems(listId: $listId, listItems: $listItems) {
id
listItems {
id
body
createdAt
username
}
}
}
`;
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;
我正在创建一个允许用户创建列表的应用程序(所有数据都存储在mongoDB上,并可以通过Apollo GraphQL访问);每个列表都有一个属性listItems,该数组将所有项目存储在...
问题太多...简要:
const [state,setState] = useState({项目:[]});
不要在钩子中使用setState
...这会引起误解,setState
用于类组件。
使用一些有意义的名称,例如itemList
:
const [itemList, setItemList] = useState( [] ); // just array
调整查询结果保存:
useEffect(() => { if (data && data.getList && data.getList.listItems) { // setState(() => ({ items: data.getList.listItems })); setItemList( data.getList.listItems ); } }, [data]);
调整可排序的更新处理程序:
const onSortEnd = ({oldIndex, newIndex}) => { // this.setState(({items}) => ({ // items: arrayMove(items, oldIndex, newIndex), // })); const newListOrder = arrayMove( itemList, oldIndex, newIndex); // console.log("array sorted", newListOrder ); // update order in local state // kind of optimistic update setItemList( newListOrder ); // update remote data editListItems( { variables: { listId, listItems: newListOrder, } });
将
onSortEnd
处理程序传递给可排序的:在这种情况下并不需要(数组已经以可排序的方式排序,我们正在更新本地数组,它将更新重新呈现),但应该在此处(变异失败/错误-从<SortableList items={itemList} onSortEnd={onSortEnd} />
Mutation应该具有
update
处理程序(writeQuery
-阅读文档),以强制查询更新/呈现。error
处理useMutation
)。类型:
input ListItemsInput: [ListItem]! ... mutation editListItems(listId: ID!, listItems: ListItemsInput): List!
在操场上尝试后端/ API(
。比较网络请求/响应的详细信息。/graphiql
)...在对前端进行编码之前,尝试变异使用变量
问题太多...简要: