Javascript React组件和Apollo客户端不工作“;“实时”;
我试图建立一个用户系统,但我感到困惑,因为它不能实时工作 我创建了一个示例来显示我的“问题”和代码。我没有添加任何类型的验证内容,只是出于示例目的 其中一些问题(我明白)是:Javascript React组件和Apollo客户端不工作“;“实时”;,javascript,reactjs,graphql,material-ui,react-apollo,Javascript,Reactjs,Graphql,Material Ui,React Apollo,我试图建立一个用户系统,但我感到困惑,因为它不能实时工作 我创建了一个示例来显示我的“问题”和代码。我没有添加任何类型的验证内容,只是出于示例目的 其中一些问题(我明白)是: 按钮操作在第二次单击时触发 数据在创建/删除后不会刷新 这是组件: import React,{Fragment,useState,useffect}来自“React”; 从“@apollo/react hooks”导入{UseVariation,useLazyQuery}; 从“../../../config/const
组件:
import React,{Fragment,useState,useffect}来自“React”;
从“@apollo/react hooks”导入{UseVariation,useLazyQuery};
从“../../../config/constants”导入{ADD_USER,LIST_USER,DELETE_USER}”;
从“notistack”导入{useSnackbar};
进口{
网格,
纸张
TextField,
按钮
排版,
MenuItem,
FormHelperText
}来自“@材料界面/核心”;
从“@material ui/icons/PersonAdd”导入AddUserIcon;
从“@material ui/core/styles”导入{withStyles}”;
从“道具类型”导入道具类型;
从“../../Table”导入表格;
常量样式=主题=>({
网格:{
页边空白:主题。间距(3)
},
图标:{
边缘光:主题。间距(2)
},
表格:{
宽度:“100%”,
marginTop:主题。间距(3),
overflowX:“自动”,
填充:主题。间距(2)
},
提交:{
页边空白:主题。间距(2)
},
容器:{
显示:“flex”,
柔性包装:“包装”
},
文本字段:{
marginLeft:theme.spating.unit,
marginRight:theme.space.unit
},
根目录:{
宽度:“100%”,
marginTop:主题。间距(3),
overflowX:“自动”,
填充:主题。间距(2)
},
标题:{
页边空白:主题。间距(2)
},
表:{
最小宽度:700
},
诺雷科德:{
textAlign:“居中”
},
按钮:{
页边空白:theme.space.unit
}
});
const Users=props=>{
常量[idState,setIdState]=useState(null);
const[emailState,setEmailState]=useState(“”);
const[passwordState,setPasswordState]=useState(“”);
常量[usersState,setUsersState]=useState([]);
常量[errorsState,setErrorsState]=useState({});
常量[loadingState,setLoadingState]=useState(false);
const[addUser,addUserResponse]=使用变异(ADD_USER);
const[loadUsers,usersResponse]=使用LazyQuery(列出用户);
const[deleteUser,deleteUserResponse]=使用变异(DELETE_USER);
const{enqueueSnackbar}=useSnackbar();
useffect(()=>{
loadUsers();
if(usersResponse.called&&usersResponse.loading){
设置加载状态(真);
}else if(usersResponse.called&!usersResponse.loading){
设置加载状态(假);
}
if(usersResponse.data){
setUsersState(usersResponse.data.getUsers);
}
},[usersResponse.called,usersResponse.loading,usersResponse.data]);
函数handleSubmit(e){
e、 预防默认值();
如果(idState){
}否则{
地址用户({
变量:{
电子邮件:emailState,
密码:passwordState
}
});
}
if(addUserResponse.called&&addUserResponse.loading){
排队Snackbar(“创建用户”);
}
if(addUserResponse.error){
addUserResponse.error.graphQLErrors.map(异常=>{
常量错误=exception.extensions.exception;
常量消息=对象值(错误);
enqueueSnackbar(消息[0],{variant:“error”});
});
}
if(addUserResponse.data&&addUserResponse.data.addUser){
enqueueSnackbar(“用户创建的”{variant:“success”});
loadUsers();
}
}
函数handleEdit(用户){
setIdState(user.id);
setEmailState(user.email);
}
异步函数handleDelete(数据){
如果(数据类型==“对象”){
data.map(id=>{
deleteUser({变量:{id}});
if(deleteUserResponse.data&&deleteUserResponse.data.deleteUser){
enqueueSnackbar(“用户已删除”{variant:“success”});
}
});
}否则{
deleteUser({变量:{id:data}});
if(deleteUserResponse.data&&deleteUserResponse.data.deleteUser){
enqueueSnackbar(“用户已删除”{variant:“success”});
}
}
}
函数resetForm(){
setIdState(空);
setEmailState(“”);
}
常量{classes}=props;
返回(
{idState?`编辑用户:${emailState}`:“创建用户”}
setEmailState(e.target.value)}
值={emailState}
aria descripeby=“电子邮件错误”
/>
{errorsState.email}
setPasswordState(e.target.value)}
值={passwordState}
aria descripeby=“密码错误”
/>
{errorsState.password}
/
后端沙盒:/
如有任何意见、建议或诸如此类,我们将不胜感激
按钮操作在第二次单击时触发
那是因为你打电话
if (addUserResponse.called && addUserResponse.loading) {
enqueueSnackbar("Creating user");
}
在您调用addUser
之后,当您选中if(addUserResponse.called&&addUserResponse.loading)
时,该状态与调用addUser
之前的状态相同
当您第二次单击时,您将获得第一次单击后的状态,如果
if (addUserResponse.data && addUserResponse.data.addUser) {
enqueueSnackbar("user created", { variant: "success" });
loadUsers();
}
这是真的
解决方案:
const [addUser, addUserResponse] = useMutation(ADD_USER, {
update: (cache, { data: { addUser } }) => {
// get current data cache
const cachedUsers = cache.readQuery({ query: LIST_USERS });
// create new users
const newUsers = [addUser, ...cachedUsers.getUsers];
// save newUsers on cache
cache.writeQuery({
query: LIST_USERS,
data: {
getUsers: newUsers
}
});
}
});
创建一个useffect
来处理addUser
状态,并从handleSubmit
useEffect(() => {
if (!addUserResponse.called) {
return;
}
if (addUserResponse.loading) {
enqueueSnackbar("Creating user");
return;
}
if (addUserResponse.error) {
addUserResponse.error.graphQLErrors.map(exception => {
const error = exception.extensions.exception;
const messages = Object.values(error);
enqueueSnackbar(messages[0], { variant: "error" });
});
return;
}
enqueueSnackbar("user created", { variant: "success" });
}, [addUserResponse.called, addUserResponse.loading]);
function handleSubmit(e) {
e.preventDefault();
if (idState) {
} else {
addUser({
variables: {
email: emailState,
password: passwordState
}
});
}
}
数据在创建/删除后不会刷新
你应该这么做,因为阿波罗不知道当你调用一个变异时你是在添加还是删除
解决方案:
const [addUser, addUserResponse] = useMutation(ADD_USER, {
update: (cache, { data: { addUser } }) => {
// get current data cache
const cachedUsers = cache.readQuery({ query: LIST_USERS });
// create new users
const newUsers = [addUser, ...cachedUsers.getUsers];
// save newUsers on cache
cache.writeQuery({
query: LIST_USERS,
data: {
getUsers: newUsers
}
});
}
});
删除用户也是如此,希望新用户
将筛选当前用户:
const [deleteUser, deleteUserResponse] = useMutation(DELETE_USER, {
update: (cache, { data: { deleteUser } }) => {
const cachedUsers = cache.readQuery({ query: LIST_USERS });
// NOTE: this didn't work because deleteUser return true instead user.
// I'd suggest change your backend and deleteUser return user id to
// be able to perform this filter.
const newUsers = cachedUsers.getUsers.filter(
({ id }) => id !== deleteUser.id
);
cache.writeQuery({
query: LIST_USERS,
data: {
getUsers: newUsers
}
});
}
});
注1:
const [addUser, addUserResponse] = useMutation(ADD_USER, {
update: (cache, { data: { addUser } }) => {
// get current data cache
const cachedUsers = cache.readQuery({ query: LIST_USERS });
// create new users
const newUsers = [addUser, ...cachedUsers.getUsers];
// save newUsers on cache
cache.writeQuery({
query: LIST_USERS,
data: {
getUsers: newUsers
}
});
}
});
您不需要多次调用loadUsers
type Mutation {
addUser(email: String!, password: String!): User
deleteUser(id: String!): User
batchDeleteUsers(ids: [String!]!): [User]
}
deleteUser: (root, { id }, context) => {
const user = USERSDB.find(user => user.id === id);
USERSDB = USERSDB.filter(user => user.id !== id);
return user;
},
batchDeleteUsers: (root, { ids }, context) => {
const users = USERSDB.filter(user => ids.includes(user.id));
USERSDB = USERSDB.filter(user => !ids.includes(user.id));
return users;
}
const usersResponse = useQuery(LIST_USERS);
const [deleteUser, deleteUserResponse] = useMutation(DELETE_USER, {
update: (cache, { data: { deleteUser } }) => {
const cachedUsers = cache.readQuery({ query: LIST_USERS });
const newUsers = cachedUsers.getUsers.filter(
({ id }) => id !== deleteUser.id
);
cache.writeQuery({
query: LIST_USERS,
data: {
getUsers: newUsers
}
});
}
});
const [batchDeleteUsers, batchDeleteUsersResponse] = useMutation(
BATCH_DELETE_USERS,
{
update: (cache, { data: { batchDeleteUsers } }) => {
const cachedUsers = cache.readQuery({ query: LIST_USERS });
const newUsers = cachedUsers.getUsers.filter(({ id }) => {
return !batchDeleteUsers.map(({ id }) => id).includes(id);
});
cache.writeQuery({
query: LIST_USERS,
data: {
getUsers: newUsers
}
});
}
}
);
useEffect(() => {
if (!deleteUserResponse.called) {
return;
}
if (deleteUserResponse.loading) {
enqueueSnackbar("Deleting user");
return;
}
if (deleteUserResponse.error) {
deleteUserResponse.error.graphQLErrors.map(exception => {
const error = exception.extensions.exception;
const messages = Object.values(error);
enqueueSnackbar(messages[0], { variant: "error" });
});
return;
}
enqueueSnackbar("user deleted", { variant: "success" });
}, [deleteUserResponse.called, deleteUserResponse.loading]);
useEffect(() => {
if (!batchDeleteUsersResponse.called) {
return;
}
if (batchDeleteUsersResponse.loading) {
enqueueSnackbar("Deleting users");
return;
}
if (batchDeleteUsersResponse.error) {
batchDeleteUsersResponse.error.graphQLErrors.map(exception => {
const error = exception.extensions.exception;
const messages = Object.values(error);
enqueueSnackbar(messages[0], { variant: "error" });
});
return;
}
enqueueSnackbar("users deleted", { variant: "success" });
}, [batchDeleteUsersResponse.called, batchDeleteUsersResponse.loading]);
function handleDelete(data) {
if (typeof data === "object") {
batchDeleteUsers({ variables: { ids: data } });
} else {
deleteUser({ variables: { id: data } });
}
}