Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 如何在双嵌套子组件网(带挂钩)中从父组件优化更新状态?_Reactjs_Graphql - Fatal编程技术网

Reactjs 如何在双嵌套子组件网(带挂钩)中从父组件优化更新状态?

Reactjs 如何在双嵌套子组件网(带挂钩)中从父组件优化更新状态?,reactjs,graphql,Reactjs,Graphql,您好,目前我的问题是,当我单击Delete按钮(在SortableItem组件中找到)时,当变异成功工作时,它需要刷新以显示删除。运行DeleteButton后,最理想的刷新方式是什么?我相信这需要我更新SortableItem组件中RankList组件的状态,但我想知道实现这一点的最佳方法 RankList.js import React, { useContext, useEffect, useRef, useState } from "react"; import gql from "gr

您好,目前我的问题是,当我单击Delete按钮(在SortableItem组件中找到)时,当变异成功工作时,它需要刷新以显示删除。运行DeleteButton后,最理想的刷新方式是什么?我相信这需要我更新SortableItem组件中RankList组件的状态,但我想知道实现这一点的最佳方法

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 DeleteButton from "../components/DeleteButton";
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";

// function SortableItem({ value, listId, listItemId }) {
//   return SortableElement(() => (
//     <>
//       <li className="listLI">{value}</li>
//       <DeleteButton listId={listId} listItemId={listItemId} />
//     </>
//   ));
// }

const SortableItem = SortableElement(
  ({ deleteItem, value, listId, listItemId }) => (
    <>
      <li className="listLI">{value}</li>
      <DeleteButton
        listId={listId}
        listItemId={listItemId}
        deleteItem={deleteItem}
      />
    </>
  )
);

const SortableList = SortableContainer(({ deleteItem, items, listId }) => {
  return (
    <ol className="theList">
      {/* <CSSTransitionGroup
        transitionName="ranklist"
        transitionEnterTimeout={500}
        transitionLeaveTimeout={300}
      > */}
      {items.map((item, index) => (
        <SortableItem
          deleteItem={deleteItem}
          listId={listId}
          listItemId={item.id}
          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,
    },
    // onError(err) {
    //   console.log(err.graphQLErrors[0].extensions.exception.errors);
    //   // setErrors(err.graphQLErrors[0].extensions.exception.errors);
    // }
  });

  useEffect(() => {
    if (data && data.getList && data.getList.listItems) {
      setState(() => ({ items: data.getList.listItems }));
    }
  }, [data]);

  // const [state, setState] = useState({ items: data.getList.listItems });

  const deleteItem = (listItem) => {
    let temp = state.items.filter((item) => item.id !== listItem);
    console.log(temp);
    setState(() => ({ items: temp }));
  };

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

    state.items.map((list) => delete list["__typename"]);

    editListItems();
  }

  let listMarkup;
  if (!data.getList) {
    listMarkup = <p>Loading list...</p>;
  } else {
    const {
      id,
      title,
      createdAt,
      username,
      listItems,
      comments,
      likes,
      likeCount,
      commentCount,
    } = data.getList;

    console.log(id);

    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
            deleteItem={deleteItem}
            items={state.items}
            listId={id}
            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"
          /> */}
          <ol className="theList">
            {/* <CSSTransitionGroup
        transitionName="ranklist"
        transitionEnterTimeout={500}
        transitionLeaveTimeout={300}
      > */}
            {listItems.map((item, index) => (
              <li
                className="listLI"
                key={`item-${item.id}`}
                index={index}
                value={item.body}
              >
                {item.body}
              </li>
            ))}
            {/* </CSSTransitionGroup> */}
          </ol>
        </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;
import React, { useState } from "react";
import gql from "graphql-tag";
import { useMutation } from "@apollo/react-hooks";

import { Button, Confirm, Icon } from "semantic-ui-react";

import { FETCH_LISTS_QUERY, FETCH_LIST_QUERY } from "../util/graphql";
import MyPopup from "../util/MyPopup";

function DeleteButton({ listId, listItemId, commentId, deleteItem, callback }) {
  const [confirmOpen, setConfirmOpen] = useState(false);

  let mutation;

  if (listItemId) {
    mutation = DELETE_LIST_ITEM_MUTATION;
  } else if (commentId) {
    mutation = DELETE_COMMENT_MUTATION;
  } else {
    mutation = DELETE_LIST_MUTATION;
  }

  // const mutation = commentId ? DELETE_COMMENT_MUTATION : DELETE_LIST_MUTATION;

  const [deleteListOrComment] = useMutation(mutation, {
    update(proxy) {
      setConfirmOpen(false);
      // remove list from cache
      if (!commentId && !listItemId) {
        const data = proxy.readQuery({
          query: FETCH_LISTS_QUERY,
        });
        const resLists = data.getLists.filter((p) => p.id !== listId);
        proxy.writeQuery({
          query: FETCH_LISTS_QUERY,
          data: { getLists: [...resLists] },
        });
      }

      if (callback) callback();
    },
    variables: {
      listId,
      listItemId,
      commentId,
    },
    onError(err) {
      console.log(err.graphQLErrors[0].extensions.exception.errors);
    },
  });

  return (
    <>
      <MyPopup content={commentId ? "Delete comment" : "Delete list"}>
        <Button
          as="div"
          color="red"
          floated="right"
          onClick={(e) => {
            e.preventDefault();
            setConfirmOpen(true);
          }}
        >
          <Icon name="trash" style={{ margin: 0 }} />
        </Button>
      </MyPopup>
      <Confirm
        open={confirmOpen}
        onCancel={(e) => {
          e.preventDefault();
          setConfirmOpen(false);
        }}
        onConfirm={(e) => {
          e.preventDefault();
          deleteListOrComment();
          deleteItem(listItemId);
        }}
      />
    </>
  );
}

const DELETE_LIST_MUTATION = gql`
  mutation deleteList($listId: ID!) {
    deleteList(listId: $listId)
  }
`;

const DELETE_LIST_ITEM_MUTATION = gql`
  mutation deleteListItem($listId: ID!, $listItemId: ID!) {
    deleteListItem(listId: $listId, listItemId: $listItemId) {
      id
      comments {
        id
        username
        createdAt
        body
      }
      commentCount
    }
  }
`;

const DELETE_COMMENT_MUTATION = gql`
  mutation deleteComment($listId: ID!, $commentId: ID!) {
    deleteComment(listId: $listId, commentId: $commentId) {
      id
      comments {
        id
        username
        createdAt
        body
      }
      commentCount
    }
  }
`;
export default DeleteButton;
import React,{useContext,useffect,useRef,useState}来自“React”;
从“graphql标签”导入gql;
从“@apollo/react hooks”导入{useQuery,useVaritation}”;
从“语义ui反应”导入{Form};
从“时刻”中导入时刻;
从“./组件/DeleteButton”导入DeleteButton;
从“./context/auth”导入{AuthContext};
从“react-sortable hoc”导入{SortableContainer,SortableElement};
从“阵列移动”导入阵列移动;
导入“./RankList.css”;
从“反应转换组”导入{CSSTransitionGroup};
//函数SortableItem({value,listId,listItemId}){
//返回可排序元素(()=>(
//     
//
  • {value}
  • // // // )); // } const SortableItem=SortableElement( ({deleteItem,value,listId,listItemId})=>(
  • {value}
  • ) ); const SortableList=SortableContainer({deleteItem,items,listId})=>{ 返回( {/* */} {items.map((项,索引)=>( ))} {/* */} ); }); 功能等级列表(道具){ 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\u LIST\u QUERY{ 变量:{ listId, }, //ONERR(错误){ //日志(err.graphQLErrors[0].extensions.exception.errors); ////setErrors(err.graphQLErrors[0].extensions.exception.errors); // } }); useffect(()=>{ if(data&&data.getList&&data.getList.listItems){ setState(()=>({items:data.getList.listItems})); } },[数据]; //const[state,setState]=useState({items:data.getList.listItems}); 常量deleteItem=(listItem)=>{ 让temp=state.items.filter((item)=>item.id!==listItem); 控制台日志(temp); setState(()=>({items:temp})); }; 常量[submitListItem]=使用突变(提交列表项突变{ 更新(){ setListItem(“”); listItemInputRef.current.blur(); }, 变量:{ listId, 正文:清单项目, }, }); 常量[editListItems]=使用变异(编辑列表项变异{ 变量:{ listId, listItems:state.items, }, }); 如果(加载)返回加载…

    ; 如果(错误)返回错误..

    ; 函数deleteListCallback(){ props.history.push(“/”); } onSortEnd({oldIndex,newIndex})函数{ setState(({items})=>({ 项目:arrayMove(项目、旧索引、新索引), })); state.items.map((list)=>delete list[“\uu typename”]); editListItems(); } 让列表标记; 如果(!data.getList){ listMarkup=加载列表…

    ; }否则{ 常数{ 身份证件 标题 创建数据, 用户名, 清单项目, 评论, 喜欢, 比如说, 伯爵, }=data.getList; console.log(id); listMarkup=用户( {title} setListItem(event.target.value)} ref={listItemInputRef} /> 提交 ) : ( {props.title} {/* */} {/* */} {listItems.map((项,索引)=>(
  • {item.body}
  • ))} {/* */} ); } 返回列表标记; } 常量编辑\列表\项目\变异=gql` 突变($listId:ID!,$listItems:[listItems]!){ editListItems(listId:$listId,listItems:$listItems){ 身份证件 列表项{ 身份证件 身体 创建数据 用户名 } } } `; const SUBMIT\u LIST\u ITEM\u MUTATION=gql` 突变($listId:ID!,$body:String!){ createListItem(listId:$listId,body:$body){ 身份证件 列表项{ 身份证件 身体 创建数据 用户名 } 评论{ 身份证件 身体 创建数据 用户名 } 评论计数 } } `; const FETCH\u LIST\u QUERY=gql` 查询($listId:ID!){ getList(listId:$listId){ 身份证件 标题 创建数据 用户名 列表项{ 身份证件 创建数据 用户名 身体 } 利克蒙特 喜欢{ 用户名 } 评论计数 评论{ 身份证件 用户名 创建数据 身体 } } } `; 导出默认RankList;
    DeleteButton.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 DeleteButton from "../components/DeleteButton";
    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";
    
    // function SortableItem({ value, listId, listItemId }) {
    //   return SortableElement(() => (
    //     <>
    //       <li className="listLI">{value}</li>
    //       <DeleteButton listId={listId} listItemId={listItemId} />
    //     </>
    //   ));
    // }
    
    const SortableItem = SortableElement(
      ({ deleteItem, value, listId, listItemId }) => (
        <>
          <li className="listLI">{value}</li>
          <DeleteButton
            listId={listId}
            listItemId={listItemId}
            deleteItem={deleteItem}
          />
        </>
      )
    );
    
    const SortableList = SortableContainer(({ deleteItem, items, listId }) => {
      return (
        <ol className="theList">
          {/* <CSSTransitionGroup
            transitionName="ranklist"
            transitionEnterTimeout={500}
            transitionLeaveTimeout={300}
          > */}
          {items.map((item, index) => (
            <SortableItem
              deleteItem={deleteItem}
              listId={listId}
              listItemId={item.id}
              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,
        },
        // onError(err) {
        //   console.log(err.graphQLErrors[0].extensions.exception.errors);
        //   // setErrors(err.graphQLErrors[0].extensions.exception.errors);
        // }
      });
    
      useEffect(() => {
        if (data && data.getList && data.getList.listItems) {
          setState(() => ({ items: data.getList.listItems }));
        }
      }, [data]);
    
      // const [state, setState] = useState({ items: data.getList.listItems });
    
      const deleteItem = (listItem) => {
        let temp = state.items.filter((item) => item.id !== listItem);
        console.log(temp);
        setState(() => ({ items: temp }));
      };
    
      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),
        }));
    
        state.items.map((list) => delete list["__typename"]);
    
        editListItems();
      }
    
      let listMarkup;
      if (!data.getList) {
        listMarkup = <p>Loading list...</p>;
      } else {
        const {
          id,
          title,
          createdAt,
          username,
          listItems,
          comments,
          likes,
          likeCount,
          commentCount,
        } = data.getList;
    
        console.log(id);
    
        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
                deleteItem={deleteItem}
                items={state.items}
                listId={id}
                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"
              /> */}
              <ol className="theList">
                {/* <CSSTransitionGroup
            transitionName="ranklist"
            transitionEnterTimeout={500}
            transitionLeaveTimeout={300}
          > */}
                {listItems.map((item, index) => (
                  <li
                    className="listLI"
                    key={`item-${item.id}`}
                    index={index}
                    value={item.body}
                  >
                    {item.body}
                  </li>
                ))}
                {/* </CSSTransitionGroup> */}
              </ol>
            </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;
    
    import React, { useState } from "react";
    import gql from "graphql-tag";
    import { useMutation } from "@apollo/react-hooks";
    
    import { Button, Confirm, Icon } from "semantic-ui-react";
    
    import { FETCH_LISTS_QUERY, FETCH_LIST_QUERY } from "../util/graphql";
    import MyPopup from "../util/MyPopup";
    
    function DeleteButton({ listId, listItemId, commentId, deleteItem, callback }) {
      const [confirmOpen, setConfirmOpen] = useState(false);
    
      let mutation;
    
      if (listItemId) {
        mutation = DELETE_LIST_ITEM_MUTATION;
      } else if (commentId) {
        mutation = DELETE_COMMENT_MUTATION;
      } else {
        mutation = DELETE_LIST_MUTATION;
      }
    
      // const mutation = commentId ? DELETE_COMMENT_MUTATION : DELETE_LIST_MUTATION;
    
      const [deleteListOrComment] = useMutation(mutation, {
        update(proxy) {
          setConfirmOpen(false);
          // remove list from cache
          if (!commentId && !listItemId) {
            const data = proxy.readQuery({
              query: FETCH_LISTS_QUERY,
            });
            const resLists = data.getLists.filter((p) => p.id !== listId);
            proxy.writeQuery({
              query: FETCH_LISTS_QUERY,
              data: { getLists: [...resLists] },
            });
          }
    
          if (callback) callback();
        },
        variables: {
          listId,
          listItemId,
          commentId,
        },
        onError(err) {
          console.log(err.graphQLErrors[0].extensions.exception.errors);
        },
      });
    
      return (
        <>
          <MyPopup content={commentId ? "Delete comment" : "Delete list"}>
            <Button
              as="div"
              color="red"
              floated="right"
              onClick={(e) => {
                e.preventDefault();
                setConfirmOpen(true);
              }}
            >
              <Icon name="trash" style={{ margin: 0 }} />
            </Button>
          </MyPopup>
          <Confirm
            open={confirmOpen}
            onCancel={(e) => {
              e.preventDefault();
              setConfirmOpen(false);
            }}
            onConfirm={(e) => {
              e.preventDefault();
              deleteListOrComment();
              deleteItem(listItemId);
            }}
          />
        </>
      );
    }
    
    const DELETE_LIST_MUTATION = gql`
      mutation deleteList($listId: ID!) {
        deleteList(listId: $listId)
      }
    `;
    
    const DELETE_LIST_ITEM_MUTATION = gql`
      mutation deleteListItem($listId: ID!, $listItemId: ID!) {
        deleteListItem(listId: $listId, listItemId: $listItemId) {
          id
          comments {
            id
            username
            createdAt
            body
          }
          commentCount
        }
      }
    `;
    
    const DELETE_COMMENT_MUTATION = gql`
      mutation deleteComment($listId: ID!, $commentId: ID!) {
        deleteComment(listId: $listId, commentId: $commentId) {
          id
          comments {
            id
            username
            createdAt
            body
          }
          commentCount
        }
      }
    `;
    export default DeleteButton;
    
    import React,{useState}来自“React”;
    从“graphql标签”导入gql;
    从“@apollo/react hooks”导入{useStation}”;
    从“语义ui反应”导入{按钮、确认、图标};
    从“./util/graphql”导入{FETCH_LIST_QUERY,FETCH_LIST_QUERY};
    从“./util/MyPopup”导入MyPopup;
    函数DeleteButton({listId,listimeid,commentId,deleteem,callback}){
    const[confirmOpen,setConfirmOpen]=useState(false);
    让突变;
    if(listItemId){
    突变=删除列表项_