programing

React에서 setState를 사용하여 개체 업데이트

i4 2023. 3. 7. 21:04
반응형

React에서 setState를 사용하여 개체 업데이트

을 브브트 object object로 갱신할 수 ?setState

예를 들어 다음과 같습니다.

this.state = {
   jasper: { name: 'jasper', age: 28 },
}

시도했습니다.

this.setState({jasper.name: 'someOtherName'});

또, 이하와 같이 됩니다.

this.setState({jasper: {name: 'someothername'}})

첫 번째 경우 구문 오류가 발생하고 두 번째 경우 구문 오류가 발생하지 않습니다.좋은 생각 있어요?

여기에는 여러 가지 방법이 있습니다.상태 갱신은 비동기 조작이기 때문에 상태 오브젝트를 갱신하기 위해서는 다음과 같이 업데이터 기능을 사용해야 합니다.setState.

1 - 가장 심플한 것:

''을 보세요.jasper하다

this.setState(prevState => {
  let jasper = Object.assign({}, prevState.jasper);  // creating copy of state variable jasper
  jasper.name = 'someothername';                     // update the name property, assign a new value                 
  return { jasper };                                 // return new object jasper object
})

「 」를 하는 대신에, 「 」를 사용합니다.Object.assign을 사용하다

let jasper = { ...prevState.jasper };

2- 확산 구문 사용:

this.setState(prevState => ({
    jasper: {                   // object that we want to update
        ...prevState.jasper,    // keep all other key-value pairs
        name: 'something'       // update the value of specific key
    }
}))

Object.assign ★★★★★★★★★★★★★★★★★」Spread Operator에서는 얕은 복사만 작성되므로 중첩된 개체 또는 개체 배열을 정의한 경우에는 다른 접근법이 필요합니다.


중첩된 상태 개체를 업데이트하는 중:

상태를 다음과 같이 정의했다고 가정합니다.

this.state = {
  food: {
    sandwich: {
      capsicum: true,
      crackers: true,
      mayonnaise: true
    },
    pizza: {
      jalapeno: true,
      extraCheese: false
    }
  }
}

추가 치즈 오브 피자 개체를 업데이트하려면:

this.setState(prevState => ({
  food: {
    ...prevState.food,           // copy all other key-value pairs of food object
    pizza: {                     // specific object of food object
      ...prevState.food.pizza,   // copy all pizza key-value pairs
      extraCheese: true          // update value of specific key
    }
  }
}))

개체 배열 업데이트 중:

ToDo 앱이 있고 다음 형식으로 데이터를 관리하고 있다고 가정합니다.

this.state = {
  todoItems: [
    {
      name: 'Learn React Basics',
      status: 'pending'
    }, {
      name: 'Check Codebase',
      status: 'pending'
    }
  ]
}

객체의 ToDo 객체의 합니다.condition=true갱신된 값을 사용하여 새 개체를 반환합니다.그렇지 않으면 동일한 개체를 반환합니다.

let key = 2;
this.setState(prevState => ({

  todoItems: prevState.todoItems.map(
    el => el.key === key? { ...el, status: 'done' }: el
  )

}))

제안:개체에 고유한 값이 없으면 배열 인덱스를 사용합니다.

이것이 가장 빠르고 읽기 쉬운 방법입니다.

this.setState({...this.state.jasper, name: 'someothername'});

this.state.jasper새, 이름 등이 이미 되어 있습니다.name: 'someothername'사용할 수 있습니다.

여기서 분산 연산자와 일부 ES6 사용

this.setState({
    jasper: {
          ...this.state.jasper,
          name: 'something'
    }
})

여기에 많은 답변이 있는 것은 알지만, 그 중 어느 것도 setState 이외의 새로운 오브젝트의 복사본을 작성하지 않고 단순히 setState({newObject})를 작성하지 않는 것이 놀랍습니다.깔끔하고 간결하며 신뢰성이 뛰어납니다.이 경우:

const jasper = { ...this.state.jasper, name: 'someothername' }
this.setState(() => ({ jasper }))

또는 동적 속성(양식에 매우 유용함)의 경우

const jasper = { ...this.state.jasper, [VarRepresentingPropertyName]: 'new value' }
this.setState(() => ({ jasper }))

후크를 사용하여 다음과 같이 할 수 있습니다.

const [student, setStudent] = React.useState({name: 'jasper', age: 28});
 setStudent((prevState) => ({
          ...prevState,
          name: 'newName',
        }));

나는 이 용액을 사용했다.

다음과 같은 중첩 상태가 있는 경우:

this.state = {
  formInputs:{
    friendName:{
      value:'',
      isValid:false,
      errorMsg:''
    },
    friendEmail:{
      value:'',
      isValid:false,
      errorMsg:''
    }
  }
}

현재 상태를 복사하고 변경된 값으로 다시 할당하는 handleChange 함수를 선언할 수 있습니다.

handleChange(el) {
    let inputName = el.target.name;
    let inputValue = el.target.value;

    let statusCopy = Object.assign({}, this.state);
    statusCopy.formInputs[inputName].value = inputValue;

    this.setState(statusCopy);
  }

이벤트 리스너와 함께 html을 만듭니다.상태 개체와 동일한 이름을 사용하십시오(이 경우 'friendName').

<input type="text" onChange={this.handleChange} " name="friendName" />

이거 해봐, 잘 될 거야

this.setState(Object.assign(this.state.jasper,{name:'someOtherName'}));

상태 개체를 만듭니다.

this.state = {
  objName: {
    propertyOne: "",
    propertyTwo: ""
  }
};

를 사용하여 합니다.setState

this.setState(prevState => ({
  objName: {
    ...prevState.objName,
    propertyOne: "Updated Value",
    propertyTwo: "Updated value"
  }
}));

이것은 immer immutabe 유틸리티를 사용하는 또 다른 솔루션이며, 쉽게 네스트된 오브젝트에 매우 적합하며, 돌연변이는 신경 쓰지 말아야 합니다.

this.setState(
    produce(draft => {
       draft.jasper.name = 'someothername'
    })
)

기능 컴포넌트의 후크 사용:

const [state, setState] = useState({jasper: { name: 'jasper', age: 28 }})
const nameChangeHandler = () => {
      setState(prevState => ({
            ...prevState,
            prevState.jasper.name = "Anurag",
            prevState.jasper.age = 28
      })
    )
}

이 경우 콜백 기반의 접근방식을 사용하여 상태를 갱신할 것을 권장합니다.이 접근방식을 사용하면 이전 상태가 완전히 갱신되고 이전에 갱신된 상태에 따라 갱신됩니다.

첫 번째 경우는 구문 오류입니다.

나머지 컴포넌트를 볼 수 없기 때문에 이 상태에서는 오브젝트를 네스트 하는 이유를 알 수 없습니다.오브젝트를 컴포넌트 상태로 중첩하는 것은 좋지 않습니다.초기 상태를 다음과 같이 설정하십시오.

this.state = {
  name: 'jasper',
  age: 28
}

이렇게 하면 이름을 갱신할 수 있습니다.

this.setState({
  name: 'Sean'
});

그것이 당신이 목표로 하는 것을 달성할 수 있습니까?

더 크고 복잡한 데이터 저장소에는 Redux와 같은 것을 사용합니다.하지만 그것은 훨씬 더 발전된 것이다.

컴포넌트 상태의 일반적인 규칙은 컴포넌트의 UI 상태(액티브, 타이머 등)를 관리하기 위해서만 사용합니다.

다음 참고 자료를 확인하십시오.

키가 문자열인 개체를 업데이트하는 경우

예: 상태 객체가 다음과 같습니다.

serviceDays: {
    Sunday: true,
    Monday: true,
    Tuesday: false,
    Wednesday: true,
    Thurday: false,
    Friday: true,
    Saturday: true
  }

따라서 다음과 같은 방법으로 업데이트 할 수 있습니다.

const onDayClick = day => {
  const { serviceDays } = this.state
  this.setState(prevState => ({
    serviceDays: {
      ...prevState.serviceDays,
      [day]: serviceDays[day] ? false : true
    }
  }))
}

다른 옵션은 Jasper 개체에서 변수를 정의하고 변수를 호출하는 것입니다.

확산 연산자: ES6

this.state = {  jasper: { name: 'jasper', age: 28 } } 

let foo = "something that needs to be saved into state" 

this.setState(prevState => ({
    jasper: {
        ...jasper.entity,
        foo
    }
})

다음과 같이 시험해 볼 수 있습니다.

this.setState(prevState => {
   prevState = JSON.parse(JSON.stringify(this.state.jasper));
   prevState.name = 'someOtherName';
   return {jasper: prevState}
})

또는 기타 속성의 경우:

this.setState(prevState => {
   prevState = JSON.parse(JSON.stringify(this.state.jasper));
   prevState.age = 'someOtherAge';
   return {jasper: prevState}
})

또는 handleChage 함수를 사용할 수 있습니다.

handleChage(event) {
   const {name, value} = event.target;
    this.setState(prevState => {
       prevState = JSON.parse(JSON.stringify(this.state.jasper));
       prevState[name] = value;
       return {jasper: prevState}
    })
}

및 HTML 코드:

<input 
   type={"text"} 
   name={"name"} 
   value={this.state.jasper.name} 
   onChange={this.handleChange}
/>
<br/>
<input 
   type={"text"} 
   name={"age"} 
   value={this.state.jasper.age} 
   onChange={this.handleChange}
/>

다음과 같이 시도해 볼 수 있습니다. (주의: 입력 태그 이름 === 객체의 필드)

<input name="myField" type="text" 
      value={this.state.myObject.myField} 
     onChange={this.handleChangeInpForm}>
</input>

-----------------------------------------------------------
handleChangeInpForm = (e) => {
   let newObject = this.state.myObject;
   newObject[e.target.name] = e.target.value;
   this.setState({
     myObject: newObject 
   })
}

심플하고 역동적인 방법

이렇게 하면 작업이 완료되지만, 모든 ID를 부모에게 설정해야 합니다. 그러면 부모가 개체 이름(id = "display")을 가리키고 개체 재스퍼 내부의 입력 요소 = 속성의 이름을 지정해야 합니다.

handleChangeObj = ({target: { id , name , value}}) => this.setState({ [id]: { ...this.state[id] , [name]: value } });

비동기 사용 안 함 및 대기 이 사용...

funCall(){    
     this.setState({...this.state.jasper, name: 'someothername'});
}

Async And Wait와 함께 사용하는 경우 이 옵션을 사용합니다.

async funCall(){
      await this.setState({...this.state.jasper, name: 'someothername'});
}

또한 Alberto Piras 솔루션에 따라 모든 "state" 객체를 복사하지 않을 경우 다음 절차를 수행합니다.

handleChange(el) {
    let inputName = el.target.name;
    let inputValue = el.target.value;

    let jasperCopy = Object.assign({}, this.state.jasper);
    jasperCopy[inputName].name = inputValue;

    this.setState({jasper: jasperCopy});
  }

다음을 사용해 보십시오.

const { jasper } = this.state; //Gets the object from state
jasper.name = 'A new name'; //do whatever you want with the object
this.setState({jasper}); //Replace the object in state

input html input name attribute를 사용하면 오브젝트 속성을 갱신하기 위해 보다 역동적인 접근을 할 수 있습니다.

html 입력명 속성

<input type="text" name="fname" handleChange={(e: any) => { updatePerson(e) }}/>
<input type="text" name="lname" handleChange={(e: any) => { updatePerson(e) }}/>

리액트 / TSX object.displaces

const [person, setPerson] = useState<IPerson>({});

   function updatePerson(e: React.ChangeEvent<HTMLInputElement>): void {
        const { name, value } = e.currentTarget;

        setPerson(prevState => {
            const newState = Object.assign(person, { [name]: value })
            return { ...prevState, ...newState };
        });
    }

FC의 예:

   const [formData, setformData] = useState({
           project_admin_permissions: {
              task_forms: false,
              auto_assign_rules: false,
              project_notes: true,
              alerts: false,
              update_criteria: true,
              project_flow: false,
              reports: false,
            }
        
          })
    
     const handleChangeCheckBox = (e) => {
       setformData({
          ...formData, project_admin_permissions: { ...formData.project_admin_permissions, [e.target.name]: e.target.checked }
    
        })
      }

이 설정은 나에게 유효했다.

let newState = this.state.jasper;
newState.name = 'someOtherName';

this.setState({newState: newState});

console.log(this.state.jasper.name); //someOtherName

두 번째 접근법이 작동하지 않는 이유는{name: 'someothername'}동등.{name: 'someothername', age: undefined}그 때문에,undefined원래 나이 값을 덮어씁니다.

네스트된 객체의 상태를 변경하는 경우 Unfound.js를 사용하는 것이 좋습니다.

this.state = {
  jasper: Record({name: 'jasper', age: 28})
}

const {jasper} = this.state
this.setState({jasper: jasper.set(name, 'someothername')})

언급URL : https://stackoverflow.com/questions/43638938/updating-an-object-with-setstate-in-react

반응형