2017-12-03 15 views
0

일부 값을 로컬 저장소에 저장했습니다. 구성 요소가 탑재되면이 값을 상태로로드하려고합니다. 그러나 추가되는 마지막 속성 만 상태에 추가됩니다. 내 localStorage에서 값을 확인한 결과 모든 값이 있습니다. 또한, 조건 블록에 변수 (desc, pic 또는 foo)를 기록하면 그 변수가 있습니다.분산 연산자를 사용하여 setState를 여러 번 연속 사용하기

블록을 상태를 다시 쓰는 경우 처음에는 다음과 같은 생각을했지만 실제로 스프레드 연산자를 올바르게 사용하고 있기 때문에 그렇지 않습니다. 모든 기존 속성 다음에 새 속성을 추가합니다.

나는 블록이 처음으로 상태가 설정되기 전에 블록이 마지막으로 실행되고 있다는 문제가 있다고 생각합니다. 로컬 저장소의 세 속성을 모두 상태로 가져올 수 있도록 코드를 작성하려면 어떻게해야합니까?

componentDidMount() { 
 

 
    const desc = window.localStorage.getItem('desc'); 
 
    const pic = window.localStorage.getItem('pic'); 
 
    const foo = window.localStorage.getItem('foo'); 
 

 
    if (desc) { 
 
     console.log(desc) //'some desc' 
 
     this.setState({ 
 
     ...this.state, 
 
     textArea: { 
 
      ...this.state.textArea, 
 
      desc: desc, 
 
     }, 
 
     },()=>console.log(this.state.textArea.desc)); //undefined 
 
    } 
 

 
    if (pic) { 
 
     console.log(pic) //'some pic' 
 
     this.setState({ 
 
     ...this.state, 
 
     textArea: { 
 
      ...this.state.textArea, 
 
      pic: pic, 
 
     }, 
 
     },()=>console.log(this.state.textArea.pic)); //undefined 
 
    } 
 

 
    if (foo) { 
 
     console.log(foo) //'some foo' 
 
     this.setState({ 
 
     ...this.state, 
 
     textArea: { 
 
      ...this.state.textArea, 
 
      foo: foo, 
 
     }, 
 
     },()=>console.log(this.state.textArea.foo)); //'some foo' 
 
    } 
 
    }
당신은 아마 당신이 통과 얕은 합병 인수하여 배치 setState를 호출 반응에 의해 체포되고있다

+3

당신은'setState()'(비동기 함수)를 3 번 ​​호출하기 때문에 매번 상태를 덮어 쓰게됩니다. 동일한 호출에서 3 가지 속성을 모두 설정해보십시오. – yberg

+0

'setState'는 여러분이 명시 적으로 정의한 것을 덮어 쓰기 만하기 때문에'this.setState ({... this.state})에 그럴 필요가 없습니다. 여기에 em을 언급하지 않으면 state props를 제거하지 않습니다. – wostex

답변

1

//what I expect state to be 
 
{ 
 
    textArea: { 
 
    desc: 'some desc', 
 
    pic: 'some pic', 
 
    foo: 'some foo' 
 
    } 
 
} 
 

 
//what the state is 
 
{ 
 
    textArea: { 
 
    foo: 'some foo' 
 
    } 
 
}

. 이렇게하면 마지막 업데이트 만 적용됩니다. 당신은 예를 들어, 한 번만 호출 setState를이 문제를 해결할 수 있습니다

componentDidMount() { 
 

 
    const desc = window.localStorage.getItem('desc'); 
 
    const pic = window.localStorage.getItem('pic'); 
 
    const foo = window.localStorage.getItem('foo'); 
 

 
    this.setState({ 
 
     textArea: Object.assign({}, 
 
      desc ? { desc } : {}, 
 
      pic ? { pic } : {}, 
 
      foo ? { foo } : {} 
 
     ) 
 
    }); 
 
    }

다른 버전을 사용하는 것이 안전합니다 업데이트 객체가 아닌 setState를 위해 업데이 트를 기능를 전달하는 것입니다 여러 통화 이상. 이 함수는 두 개의 인수, 즉 이전 상태와 현재 소품을 전달합니다. 함수에서 반환 한 내용은 모두 새 상태로 설정됩니다.

componentDidMount() { 
 

 
    const desc = window.localStorage.getItem('desc'); 
 
    const pic = window.localStorage.getItem('pic'); 
 
    const foo = window.localStorage.getItem('foo'); 
 

 
    this.setState(prevState => { 
 
     if (desc) { 
 
      return { 
 
       textArea: { 
 
        ...prevState.textArea, 
 
        desc 
 
       } 
 
      } 
 
     } else { 
 
      return prevState; 
 
     } 
 
    }); 
 
    // Repeat for other properties 
 
    }
그것은 좀 더 자세한이 방법을 사용하고 있지만, 테스트 용이성을위한 구성 요소의 외부 상태 업데이트 기능을 추출 할 수있는 기회 제공 않습니다

// Outside component 
 
    const updateSubProperty = (propertyName, spec) => prevState => { 
 
     return { 
 
      [propertyName]: { 
 
      ...prevState[propertyName], 
 
      ...spec 
 
      } 
 
     } 
 
    } 
 

 
    const filterNullProperties = obj => { 
 
     return Object.keys(obj).reduce((out, curr) => { 
 
      return obj[curr] ? { ...out, [curr]: obj[curr] } : out; 
 
     }, {}); 
 
    } 
 

 
    componentDidMount() { 
 
     this.setState(updateSubProperty("textArea", 
 
      filterNullProperties(
 
       desc: window.localStorage.getItem('desc'), 
 
       pic: window.localStorage.getItem('pic'), 
 
       foo: window.localStorage.getItem('foo') 
 
     ) 
 
    )); 
 
    }

이 방법은 약간의 복잡성을 추가하지만 (내 의견)는 우리가 성취하려고 시도했던 것을 우리의 미래의 자아에게 분명히 밝히는 정말 읽기 쉬운 구성 요소를 제공합니다.