validateNext(this.state,nextState)
this.state ≠ nextState 면 true값을 반환, 해당 조건을 만족하는 경우만 컴포넌트 렌더링
this.setState = (nextState) => { const condition = validateNext(this.state, nextState) console.log(condition) if (validateNext3(this.state, nextState)) { this.state = nextState this.render() } }
validateNext 코드
이미 key가 존재하는 지 validateState로 검증을 한 후라서 key의 값만 비교함
//setState시 this.state !== nextState면 return true export const validateNext = (state, nextState) => { const keys = Object.keys(state) let result = false // false로 초기화한 뒤 아래 forEach에서 값이 다른 경우만 true로 바뀜 keys.forEach((key) => { if (state[key] !== nextState[key]) { result = true // 여기서 값이 다르면 콘솔 창 result = true 가 찍힘 근데 최종 결과 값은 result = false return } else if (key === 'nodes' || key === 'paths') { //배열은 참조가아니라 값을 비교 const thisArray = state[key] const nextArray = nextState[key] if (thisArray.length === nextArray.length) { //배열 길이가 같을 때만 순회, 두 객체데이터를 재귀함수로 비교 thisArray.forEach((object, index) => { validateNext(object, nextArray[index]) }) } else { result = true return } } }) console.log(result) // keys.forEach()를 돌지 않고 바로 return false 하네? forEach가 전부 끝난 다음 retrun을 하게 하려면 어떻게 할까? return result }
- state[key],nextState[key] 로 속성 값에 접근해 비교하는 데 다른 경우 result= true를 넣고 반복문을 끝냄
- 만약 같은데 key값이 paths, nodes라 배열이라면 참조값이 아닌 실제 값을 비교해줘야 됨
- 배열의 길이가 다른 경우는 당연히 다른 값이니, 같은 경우만 해당 배열을 돌면서 객체데이터를 뽑아 validateNext() 를 재귀적으로 사용
- forEach문이 끝난 뒤 result (boolean)을 반환
문제점
- forEach문을 돌기 전에 result를 반환해서 항상 false가 찍힘
어쩌지?
- forEach 다음에 result를 반환하도록 실행순서를 조작하자!
노력 1) forEach 반환 값을 return해보자 - 실패
export const validateNext2 = (state, nextState) => { const keys = Object.keys(state) let result = keys.forEach((key) => { if (state[key] !== nextState[key]) { return true } else if (key === 'nodes' || key === 'paths') { const thisArray = state[key] const nextArray = nextState[key] if (thisArray.length === nextArray.length) { thisArray.forEach((object, index) => { validateNext(object, nextArray[index]) }) } else { return true } } return false }) console.log(result) // keys.forEach()를 돌지 않고 바로 return하네? forEach가 전부 끝난 다음 retrun을 하게 하려면 어떻게 할까? return result // }
- return result가 forEach보다 먼저 실행되서 해당 컴포넌트에 undefined로 찍힘
- 얘는 그래도 console.log(result)는 forEach보다 나중에 실행되서 true로 찍힘
노력 2) 그럼 promise로 실행순서를 조작하자 - 실패
아래처럼 validateNext를 promise 형태로 바꾸고
export const validateNext3 = async (state, nextState) => { const keys = Object.keys(state) let result = await new Promise((resolve, reject) => { keys.forEach((key) => { if (state[key] !== nextState[key]) { resolve(true) return } else if (key === 'nodes' || key === 'paths') { const thisArray = state[key] const nextArray = nextState[key] if (thisArray.length === nextArray.length) { thisArray.forEach((object, index) => { validateNext(object, nextArray[index]) }) } else { resolve(true) return } } resolve(false) }) }) console.log(result) // true가 찍힘 return await result }
해당 컴포넌트로 보내면
this.setState = async(nextState) => { const condition = await validateNext3(this.state, nextState) console.log(condition) //아예 안찍힘 if ( await validateNext3(this.state, nextState)) { this.state = nextState this.render() } }
인식을 못함, await validateNext3(this.state, nextState)가 아예 안찍힘
노력 3) 그럼 then으로 promise 데이터를 받아올까? - 실패
// promise export const validateNext4 = async (state, nextState) => { const keys = Object.keys(state) await new Promise((resolve, reject) => { keys.forEach((key) => { if (state[key] !== nextState[key]) { resolve(true) return } else if (key === 'nodes' || key === 'paths') { const thisArray = state[key] const nextArray = nextState[key] if (thisArray.length === nextArray.length) { thisArray.forEach((object, index) => { validateNext(object, nextArray[index]) }) } else { resolve(true) return } } resolve(false) }) }).then((result) => { console.log(result) // true가 찍힘 return result // 여기선 then이라 await를 할 필요가 없는데... 값이 안나와 }) }
then의 result가 true로 찍히지만 해당 컴포넌트는 여전히 인식을 못해 아무것도 콘솔창에 나오지 않아...
질문
- forEach문 다음에 result를 반환하려면 어떻게 해야할까? 재귀에서 빠져 나온 다음 return false로 내려오는 데 이거 값을 따로 받아서 return해야 되지 않나?
노력 4) 간단히 this.state ≠ nextState 비교 실패
- setState를 할 때마다 새로운 객체를 nextState로 넣고 있다. (실제 값이 같아도 참조값이 달라짐)
this.setState({ ...this.state, paths: [...this.state.paths, node] })
이경우 항상 this.state ≠ nextState이기 때문에 같은 값일 때도 렌더링이 발생한다.
CS 스터디this.setState = (nextState) => { if (this.state !== nextState ) { this.state = nextState this.render() } }