programing

useState() 후크는 새 값을 설정할 때 개체에서 필드를 제거함

prostudy 2022. 3. 13. 11:04
반응형

useState() 후크는 새 값을 설정할 때 개체에서 필드를 제거함

내가 여기서 뭘 잘못하고 있는지 이해할 수 없어.나는 매우 간단한 오브젝트 상태를 가지고 있다.

const [itemInput, setItemInput] = useState({
    userId: userId,
    objectId: id,
    title: "",
    description: "",
    createdAt: new Date().getTime().toString(),
  })

그렇다면, 나는 그 정보를 바꾸는 입력을 가지고 있다.title필드:

const onChange = (e) => {
    setItemInput((prevState) => ({
      ...prevState,
      [e.target.name]: e.target.value,
    }));
  };

그리고 이런 식이다.onChange사용:

<input
        type="text"
        className="item-description-input"
        placeholder="Add description..."
        name="title"
        value={itemInput.title}
        onChange={onChange}
      />

GraphQL 끝점:

export const CREATE_ITEM = gql`
  mutation createItem($itemInput: ItemInput!) {
    createItem(itemInput: $itemInput) {
      userId
      objectId
      title
      description
      createdAt
    }
  }
`;

제출 기능:

const onAddItemClick = (e) => {
    e.preventDefault();
    createItem({
      variables: {
        itemInput: itemInput,
      },
    }).then((res) => {
      console.log(res);
    });
  };

제출 시 다음과 같은 정보를 얻는다.

message: "Variable "$itemInput" got invalid value { title: "ddd" }; Field "userId" of required type "MongoId!" was not provided." 

그리고 이 오류는 나머지 모든 필드에 반복되지만title.

만약 내가console.log(itemInput)기능 구성요소가 로드되면, 나는 물체의 초기 상태를 얻는다.그러나 내가 덧붙인다면console.log(itemInput)다음에onChange, 나는 단지 얻는다.{title: "some_added_text"}. onChange는 개체에서 다른 필드를 제거하며, 제출 시 graphQL 끝점은 다른 필드가 제공되지 않는 오류를 반환한다.내가 모든 것을 바르게 하고 있는 것 같아서, 이것은 매우 좌절스럽다.

UPD: 구성 요소 추가. Object구성요소는 객체 목록을 얻는다.각각의Object가지다Items문제가 되는 코드는Items새 구성 요소를 추가하려는 경우Item그 점에 있어서Object.

개체(상위) 구성 요소:

import React, { useState, useReactiveVar, Fragment } from "react";
import { useMutation } from "@apollo/client";
import CREATE_OBJECT from "../../mutations/Object";
import { objectsVar } from "../../cache";

//Components
import ItemContainer from "./ItemContainer";

const Container = ({ data, userId, color }) => {
  const [objectInput, setobjectInput] = useState({
    title: "",
    userId: userId,
    createdAt: new Date().getTime().toString(),
    color: color,
  });

  const [createObject] = useMutation(CREATE_OBJECT);

  const onAddClick = (e) => {
    e.preventDefault();
    createObject({
      variables: {
        objectInput: objectInput,
      },
    }).then((res) => {
      setobjectInput({
        title: "",
        userId: userId,
        createdAt: new Date().getTime().toString(),
        color: color,
      });
    });
  };
  
  // This works perfectly fine!! 
  const onChange = (e) => {
    setobjectInput({ ...objectInput, [e.target.name]: e.target.value });
  };

  objectsVar(data);
  const objects = useReactiveVar(objectsVar);

  return (
    <div>
      <div>
        <input
          type="text"
          placeholder="Add description..."
          name="title"
          value={objectInput.title}
          onChange={onChange}
        />
      </div>
      <div onClick={onAddClick}>Add object</div>
      {objects && objects.getAllObjects.length === 0 ? (
        <p>No objects</p>
      ) : (
        <Fragment>
          {objects &&
            objects.getAllActiveSwimlines.map(({ _id, title, items }) => (
              <ItemContainer key={_id} id={_id} title={title} userId={userId} items={items} />
            ))}
        </Fragment>
      )}
    </div>
  );
};

export default Container;

항목(하위) 구성 요소:

import React, { useState, Fragment } from "react";
import ItemContainer from "../Item/ItemContainer";
import { useMutation } from "@apollo/client";
import { CREATE_ITEM } from "../../mutations/Item";

const ItemContainer = ({ id, title, items, userId }) => {
  const [itemInput, setItemInput] = useState({
    userId: userId,
    objectId: id,
    title: "initial state",
    description: "test desc",
    createdAt: new Date().getTime().toString(),
  });

  // This doesn't work!
  const onChange = (e) => {
    const { name, value } = e.target;
    setItemInput({
      ...itemInput,
      [name]: value,
    });
  };

  const [createItem] = useMutation(CREATE_ITEM);

  const onAddItemClick = (e) => {
    e.preventDefault();
    createItem({
      variables: {
        itemInput: itemInput,
      },
    }).then((res) => {
      setItemInput({
        userId: userId,
        objectId: id,
        title: "",
        description: "",
        createdAt: new Date().getTime().toString(),
      });

      console.log(res);
    });
  };

  const newItemInput = (
    <div>
      <input
        type="text"
        placeholder="Add description..."
        name="title"
        value={itemInput.title}
        onChange={onChange}
      />
      <div onClick={onAddItemClick}>Add item</div>
    </div>
  );

  const itemContent = (
    <div>
      <Fragment>
        {items &&
          items.getObjectItems.map(({ _id, title }) => (
            <Item key={_id} id={_id} title={title} />
          ))}
      </Fragment>
    </div>
  );

  return (
    <div>
      {newItemInput}
      {itemContent}
    </div>
  );
};

export default ItemContainer;

내가 뭘 놓쳤지?

액세스하기 때문에e.target.name그리고e.target.value업데이트 기능 내에서 즉시 평가되지 않으며, 평가될 때까지 합성 이벤트 개체가 재사용된다.나머지 코드를 그대로 유지하려면 전화해서 수정하면 된다.e.persist()을 시작할 때onChange또는 이벤트에서 관련 정보를 복사하십시오.

  const onChange = (e) => {
    const {name, value} = e.target
    setItemInput((prevState) => ({
      ...prevState,
      [name]: value,
    }));
  };

또는 업데이트 기능을 해제하고 상태를 직접 설정할 수 있다(삭제된 다른 답변에서도 제안됨).

  const onChange = (e) => {
    setItemInput({
      ...itemInput,
      [e.target.name]: e.target.value,
    });
  };

참조URL: https://stackoverflow.com/questions/65887087/usestate-hook-removes-fields-from-the-object-when-setting-new-value

반응형