탭탭카드놀이) 자식컴포넌트에서 부모컴포넌트의 state 변경하기

2022. 3. 21. 13:53프로그래밍/개인프로젝트

 

자식 컴포넌트에서 부모 컴포넌트의 state를 수정하는 기능을 구현하는데 필요 없는 코드들이 많아서 모두 작성하진 않았습니다.

빠진 코드들도 굉장히 많고 제대로 작동하려면 필요한 코드들이 많기 때문에 

전체 코드를 보고 참고하시는 걸 추천드리며 깃헙에서 보실 수 있습니다

 

https://github.com/coqoa/tabtabcard


코드 상태?

// WordPlay.js
import { WordCardLevel } from "../component/CardDefault";

const WordPlay = ({navigation}) => {

    const [cardSelector, setCardSelector] = useState("word1LV");
    // cardSelector에 word1LV라는 문자열을 담아놓고
    
    return( 
      <Main>
        {(()=>{
            return (<WordCardLevel level={cardSelector} />)
            // Main에서 WordCardLevel을 불러오는데 props로 cardSelector props를 담아준다
        })()}
      </Main>
    )
}

부모 컴포넌트인 WordPlay.js에서는 cardSelector state의 값을 자식 컴포넌트로 보내는데 

cardSelector의 값에 따라 레벨이 다른 자식 컴포넌트를 가져오도록 구현했다

// CardDefault.js
export const WordCardLevel = (props) => {

    const [clearModalToggle, setClearModalToggle] = useState(false);
    
    const lastListModalOn = () => {
    	setClearModalToggle((prev) => !prev)
    };
    
    const childComponentClick = () => {
    	console.log(props)
    }
    
    const levelConsole = () => {
    	<FlatList 
            data={WordCardArray}
            onEndReached={lastListModalOn}
            onEndReachedThreshold={0.1}
            	// 리스트의 마지막에 모달창을 띄우는 토글함수를 불러온다
            renderItem = {({item})=>{
            	// render할 코드들을 작성하는 영역
            }} 
        />
        
        {clearModalToggle ? (
            // FlatList에서 토글함수를 통해 clearModalToggle의 값이 true가 되면 뜨는 모달창
            <ClearModalContainer>
                <ClearModal>
                    <NextLevel onPress={()=> childComponentClick()}>
                        <NextLevelText>다음레벨 도전!</NextLevelText>
                    </NextLevel>
                </ClearModal>
            </ClearModalContainer>
        ):null} 
    }
	return(levelConsole())
}

마지막에 뜨는 모달 창에서 '다음레벨 도전!'버튼을 클릭하면 childComponentClick함수를 실행하도록 구현했고

childComponentClick에서 console.log를 통해 props의 값을 출력하면 다음과 같이 뜬다

Object {
  "level": "word1LV",
}

 

다음 레벨로 넘어가기 위해선 부모의 cardSelector값을 "word2LV"로 변경해야 하는데 

자식 컴포넌트에서 props를 직접적으로 수정할 수 없다

(예를 들어 props.level="word2LV" 이런 방식으로는 불가능)

 

그래서 부모 컴포넌트에서 제공하는 props에 cardSelector를 변경할 수 있는 함수(getData함수) 를 추가로  넘기고

자식 컴포넌트에선 getData함수를 통해 부모 컴포넌트의 cardSelector state를 변경할 수 있다

 

최종 코드 

// WordPlay.js
import { WordCardLevel } from "../component/CardDefault";

const WordPlay = ({navigation}) => {

    const [cardSelector, setCardSelector] = useState("word1LV");
    
     ------------------- ⬇︎ 변경부분 -------------------
    const getData = (cardSelector) => {
        setCardSelector(cardSelector)
    }
    
    return( 
		<Main>
            {(()=>{
            ------------------- ⬇︎ 변경부분 ------------------- 
                return (<WordCardLevel level={cardSelector} getData={getData} /> />)
            })()}
        </Main>
    )
}
// CardDefault.js
export const WordCardLevel = (props) => {

    const [clearModalToggle, setClearModalToggle] = useState(false);
    
    const lastListModalOn = () => {
    	setClearModalToggle((prev) => !prev)
    };
    ------------------- ⬇︎ 변경부분 -------------------
    const childComponentClick = () => {
        props.getData('word2LV')
        setRefresh((prev) => !prev) // 새로고침을 위해 화면을 지우는 코드
        setClearModalToggle((prev) => !prev) // 모달창을 닫기위한 코드
        setTimeout(function() {  //새로고침을 위해 화면을 다시 켜는 코드
            setRefresh((prev) => !prev)
        },100)
    }
    
    const levelConsole = () => {
    	<FlatList 
        	data={WordCardArray}
            
            onEndReached={lastListModalOn}
            onEndReachedThreshold={0.1}
            	// 리스트의 마지막에 모달창을 띄우는 토글함수를 불러온다
            renderItem = {({item})=>{
            	//FlatList로 WordCardArray.js의 데이터를 불러오는 코드
            }} 
        />
        
        {clearModalToggle ? (
            <ClearModalContainer>
                <ClearModal>
                    <NextLevel onPress={()=> childComponentClick()}>
                        <NextLevelText>다음레벨 도전!</NextLevelText>
                    </NextLevel>
                </ClearModal>
            </ClearModalContainer>
        ):null} 
    }
	return(levelConsole())
}

참고 : https://technicolour.tistory.com/56