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 } });
      }
    }