我在反应中有一个 AutoSave 组件,我将如何根据以前的状态检查 saveData 道具,以便我只获取新的 vals

问题描述

我在下面的代码底部一个自动保存组件,它接收一个 saveData 属性,它是表值的状态,当编辑字段时,这个状态会在 onblur 上更新。现在我想获取该 saveData 并将其与 onblur 之后的先前状态进行比较,因此我只获取更改的键值并运行突变以保存它们。否则我将不得不对每个值运行一个突变,并且一旦表已满,将会有很多。

提前感谢您的帮助。

我正在尝试在这里比较旧状态和新状态,所以这可能是一个更好的起点。

I have two arrays with objects inside that I want to compare the values and return the change key value pait and array position

这是我目前的代码


const DECOR_VALUES = gql`
  query GetDecorValues($id: ID!) {
    findUserByID(id: $id) {
      decor {
        data {
          purchaseDate
          description
          alterations
          cost
          pieces
          category
          purchaser
          image
          itemNum
          _id
        }
      }
    }
  }
`;

const UPDATE_DECOR_DOC = gql`
  mutation UpdateDecorDoc(
    # $ownerID: ID!
    $description: String!
    $pieces: Int!
    $purchaser: String!
    $alterations: Boolean!
    $cost: Int!
    $purchaseDate: Date!
    $category: String!
    $image: String!
    $itemNum: Int!
  ) {
    updateDecor(
      data: {
        description: $description
        pieces: $pieces
        purchaser: $purchaser
        alterations: $alterations
        cost: $cost
        purchaseDate: $purchaseDate
        category: $category
        image: $image
        itemNum: $itemNum
        # owner: { connect: $ownerID }
      }
    ) {
      description
    }
  }
`;

const Styles = styled.div`
  padding: 1rem;

  table {
    border-spacing: 0;
    border: 1px solid black;
    tr {
      :last-child {
        td {
          border-bottom: 0;
        }
      }
    }

    th,td {
      margin: 0;
      padding: 0.5rem;
      border-bottom: 1px solid black;
      border-right: 1px solid black;

      :last-child {
        border-right: 0;
      }

      input {
        font-size: 1rem;
        padding: 0;
        margin: 0;
        border: 0;
      }
      &:hover {
        background: lightpink;
      }
    }
  }

  .pagination {
    padding: 0.5rem;
  }
`;

// Create an editable cell renderer
const EditableCell = ({
  value: initialValue,row: { index },column: { id },updateMyData,// This is a custom function that we supplied to our table instance
}) => {
  // We need to keep and update the state of the cell normally
  const [value,setValue] = React.useState(initialValue);

  const onChange = (e) => {
    setValue(e.target.value);
  };
  const onChangeDate = (e) => {
    setValue(e);
  };

  const onChangeCheck = (e) => {
    setValue(e.target.checked);
  };

  // We'll only update the external data when the input is blurred
  const onBlur = () => {
    updateMyData(index,id,value);
  };

  // If the initialValue is changed external,sync it up with our state
  React.useEffect(() => {
    setValue(initialValue);
  },[initialValue]);

  if (id === "col3") {
    return (
      <input
        type="checkBox"
        defaultChecked={value}
        onChange={onChangeCheck}
        onBlur={onBlur}
      />
    );
  }

  if (id === "col1") {
    return (
      <ReactDatePicker
        onCalendarClose={onBlur}
        selected={new Date(value)}
        onChange={onChangeDate}
      />
    );
  }

  return <input value={value} onChange={onChange} onBlur={onBlur} />;
};

// Set our editable cell renderer as the default Cell renderer
const defaultColumn = {
  Cell: EditableCell,};

const fetcher = (url) => fetch(url).then((r) => r.json());

export default function DecorData() {
  const { data: user,error: userError } = useSWR("/api/user",fetcher);

  const { data: cookieData,error: cookieError } = useSWR(
    "/api/cookie",fetcher
  );

  var cookieBearer = `Bearer ${cookieData}`;

  if (!user || !cookieData) return <p>Loading</p>;
  if (userError) return <p>{userError.message}</p>;
  if (cookieError) return <p>{cookieError.message}</p>;

  return (
    <Layout>
      <h1>View your Decor Catalog Table Here</h1>
      {user && cookieBearer && (
        <Table user={user} cookieBearer={cookieBearer} />
      )}
    </Layout>
  );
}

const Table = ({ user,cookieBearer }) => {
  const { loading,error,data: decorData } = useQuery(DECOR_VALUES,{
    variables: { id: user.id },context: {
      headers: {
        authorization: cookieBearer,},});

  const massaged = decorData?.findUserByID?.decor?.data?.map((item) => {
    var col = Object.values(item);
    console.log("item");
    console.log(decorData);
    console.log("item");
    return col.map((colItem,i) => {
      return { [`col${i}`]: colItem };
    });
  });

  const massaged1 = decorData?.findUserByID?.decor?.data?.map((item,int) => {
    var col = Object.keys(item);
    return col?.map((colItem,i) => {
      console.log(colItem);
      if (colItem === "image") {
        return {
          Header: colItem,accessor: `col${i}`,Cell: ({ cell: { value } }) => <ImageComp value={value} />,};
      }
      return {
        Header: colItem,};
    });
  });

  const result = massaged?.map((a) => Object.assign({},...a));

  if (loading) return <p>Loading</p>;
  if (error) return <p>{error.message}</p>;
  if (!decorData) return <p>No Decord Data</p>;

  return (
    <>
      {result && massaged1 && <TryThis cookieBearer={cookieBearer} result={result} massaged1={massaged1} />}
    </>
  );
};

const ImageComp = ({ value }) => {
  return (
    <>
      <img src={value} width="400" />
      <button>Replace Image</button>
    </>
  );
};

function TryThis({ result,massaged1,cookieBearer }) {
  const [data,setData] = React.useState(result); //bad naming here
  // const [originalData] = React.useState(data)
  const [skipPageReset,setSkipPageReset] = React.useState(false);

  const updateMyData = (rowIndex,columnId,value) => {
    // We also turn on the flag to not reset the page
    setSkipPageReset(true);
    setData((old) => {
      // console.log(old);
      return old.map((row,index) => {
        if (index === rowIndex) {
          return {
            ...old[rowIndex],[columnId]: value,};
        }
        return row;
      });
    });
  };

  // After data chagnes,we turn the flag back off
  // so that if data actually changes when we're not
  // editing it,the page is reset
  React.useEffect(() => {
    setSkipPageReset(false);
  },[data]);

  return (
    <>
      {/* {result && massaged1 && (
        <TableRendered result={result} massaged1={massaged1} />
      )} */}
      {data && result && massaged1 && (
        <Styles>
          {/* <button onClick={resetData}>Reset Data</button> */}
          <Table1
            columns={massaged1[0]}
            data={data}
            updateMyData={updateMyData}
            skipPageReset={skipPageReset}
            cookieBearer={cookieBearer}
          />
        </Styles>
      )}
    </>
  );
}

function Table1({ columns,data,skipPageReset,cookieBearer }) {
  // For this example,we're using pagination to illustrate how to stop
  // the current page from resetting when our data changes
  // Otherwise,nothing is different here.
  const {
    getTableProps,getTableBodyProps,headerGroups,prepareRow,page,canPrevIoUsPage,canNextPage,pageOptions,pageCount,gotoPage,nextPage,prevIoUsPage,setPageSize,state: { pageIndex,pageSize },} = useTable(
    {
      columns,defaultColumn,// use the skipPageReset option to disable page resetting temporarily
      autoResetPage: !skipPageReset,// updateMyData isn't part of the API,but
      // anything we put into these options will
      // automatically be available on the instance.
      // That way we can call this function from our
      // cell renderer!
      updateMyData,usePagination
  );

  // Render the UI for your table
  return (
    <>
      <table {...getTableProps()}>
        <thead>
          {headerGroups.map((headerGroup) => (
            <tr {...headerGroup.getHeaderGroupProps()}>
              {headerGroup.headers.map((column) => (
                <th {...column.getHeaderProps()}>{column.render("Header")}</th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody {...getTableBodyProps()}>
          {page.map((row,i) => {
            prepareRow(row);
            return (
              <tr {...row.getRowProps()}>
                {row.cells.map((cell) => {
                  return (
                    <td {...cell.getCellProps()}>{cell.render("Cell")}</td>
                  );
                })}
              </tr>
            );
          })}
        </tbody>
      </table>
      <div className="pagination">
        <button onClick={() => gotoPage(0)} disabled={!canPrevIoUsPage}>
          {"<<"}
        </button>{" "}
        <button onClick={() => prevIoUsPage()} disabled={!canPrevIoUsPage}>
          {"<"}
        </button>{" "}
        <button onClick={() => nextPage()} disabled={!canNextPage}>
          {">"}
        </button>{" "}
        <button onClick={() => gotoPage(pageCount - 1)} disabled={!canNextPage}>
          {">>"}
        </button>{" "}
        <span>
          Page{" "}
          <strong>
            {pageIndex + 1} of {pageOptions.length}
          </strong>{" "}
        </span>
        <span>
          | Go to page:{" "}
          <input
            type="number"
            defaultValue={pageIndex + 1}
            onChange={(e) => {
              const page = e.target.value ? Number(e.target.value) - 1 : 0;
              gotoPage(page);
            }}
            style={{ width: "100px" }}
          />
        </span>{" "}
        <select
          value={pageSize}
          onChange={(e) => {
            setPageSize(Number(e.target.value));
          }}
        >
          {[10,20,30,40,50].map((pageSize) => (
            <option key={pageSize} value={pageSize}>
              Show {pageSize}
            </option>
          ))}
        </select>
      </div>
      <pre>
        <code>
          {JSON.stringify(
            {
              data,null,2
          )}
        </code>
      </pre>
      {cookieBearer&& <AutoSave cookieBearer={cookieBearer} saveData={data} />}
    </>
  );
}

function AutoSave({ saveData,cookieBearer }) {
  const [saving,setSaving] = useState(false);

  const [
    updateDecorDoc,{ data: docData,loading: saving },] = useMutation(UPDATE_DECOR_DOC,{
    context: {
      headers: {
        authorization: cookieBearer,});

  const debounceSave = useCallback(
    debounce(async (saveData) => {
      console.log("save data");
      console.log(saveData);
      console.log("save data");
    })
  );

  useEffect(() => {
    if (saveData) {
      debounceSave(saveData);
    }
  },[saveData,debounceSave]);

 return null
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)