react 수업

12. lifting state up

gongmille 2024. 9. 7. 14:12

여러개의 컴포넌트에서 한 state를 공유 하는 것

 

-shared state

하위 컴포넌트가 공통된 부모 컴포넌트의 state를 공유하여 사용하는 것

 

function BoilingVerdict(props){
	if(props.celsius >= 100){
    	return <p>물이 끓습니다.</p>
    }
    return <p>물이 끓지 않습니다.</p>
}

예시 - 자식 컴포넌트

 

function Calculator(props){
	const [temperature, setTemperature] = useSate('');
    
    const handleChange = (event) => {
    	setTemperature(event.target.value);
    }
    
    return(
    	<fieldset>
        	<legend>섭씨 온도를 입력하세요 :</legend>
            <input value={temperature} onChange={handleChange} />
            <BoilingVerdict celsius={parseFloat(temperature)} />
        </fieldset>
    );
}

예시 - 부모 컴포넌트

 

다만 이 경우 온도만 입력하므로 섭씨와 화씨 단위로 입력 받을 수 있게 수정하면 다음과 같다.

 

const scaleNames={
	c:'섭씨',
    f:'화씨'
};

function TemperatureInput(props){
	const [temperature, setTemperature] = useState('');
    
    const handleChange = (event) => {
    	setTemperature(event.target.value);
    };
    
    return(
    	<fieldset>
        	<legend>
            	온도를 입력해주세요(단위:{scaleNames[props.scale]};
            </legend>
            <input value={temperature} onChange={handleChange} />
        </fieldset>
    );
}

function Calculator(props){
    return(
    	<div>
        	<TemperatureInput scale="c" />
            <TemperatureInput scale="f" />
        </duv>
    );
}

예시 - 입력값 동기화 전

 

function BoilingVerdict(props){
	if(props.celsius >= 100){
    	return <p>물이 끓습니다.</p>
    }
    return <p>물이 끓지 않습니다.</p>
}

function toCelsius(fahrenheit){
	return (fahrenheit-32)*5/9;
}

function toFahrenheit(celsius){
	return (celsius*9/5)+32;
}

function tryConvert(temperature, convert){
	const input=parseFloat(temperature);
    if(Number.isNaN(input)){
    	return '';
    }
    const output = convert(input);
    const rounded = math.round(output*1000)/1000;
    return rounded.toString();
}

function Calculator(props){
	const [temperature, setTemperature] = useState('');
    const [scale, setScale] = useState('c');
    
    const handleCelsiusChange = (temperature) => {
    	setTemperature(temperature);
        setScale('c');
    }
    const handleFahrenheitChange = (temperature) => {
    	setTemperature(temperature);
        setScale('f');
    }
    
    const celsius = scale === 'f' ? tryConvert(temperature, toCelsius) : temperature;
    const fahrenheit = scale === 'c' ? tryConvert(temperature, toFahrenheit) : temperature;
    
    return(
    	<div>
        	<TemperatureInput scale="c" temperature={celsius} onTemperatureChange={handleCelsiusChange} />
            <TemperatureInput scale="f" temperature={fahrenheit} onTemperatureChange={handleFahrenheitChange}/>
        	<BoilingVerdict  celsius={parseFloat(seleuius)} />
        </div>
    );
}

const scaleNames={
	c:'섭씨',
    f:'화씨'
};

function TemperatureInput(props){
    const handleChange = (event) => {
    	props.onTemperatureChange(event.target.value);
    };
    
    return(
    	<fieldset>
        	<legend>
            	온도를 입력해주세요(단위:{scaleNames[props.scale]});
            </legend>
            <input value={props.temperature} onChange={handleChange} />
        </fieldset>
    );
}

예시 - 동기화 처리

 

-실습

위의 예제를 실제로 실행해보자

 

const scaleNames={
	c:'섭씨',
    f:'화씨'
};

function TemperatureInput(props){
    const handleChange = (event) => {
    	props.onTemperatureChange(event.target.value);
    };
    
    return(
    	<fieldset>
        	<legend>
            	온도를 입력해주세요(단위:{scaleNames[props.scale]});
            </legend>
            <input value={props.temperature} onChange={handleChange} />
        </fieldset>
    );
}

export default TemperatureInput;

TemperatureInput.jsx

 

import React, {useState} from "react";
import TemperatureInput from "./TemperatureInput";

function BoilingVerdict(props){
	if(props.celsius >= 100){
    	return <p>물이 끓습니다.</p>
    }
    return <p>물이 끓지 않습니다.</p>
}

function toCelsius(fahrenheit){
	return ((fahrenheit-32)*5)/9;
}

function toFahrenheit(celsius){
	return (celsius*9)/5+32;
}

function tryConvert(temperature, convert){
	const input=parseFloat(temperature);
    if(Number.isNaN(input)){
    	return '';
    }
    const output = convert(input);
    const rounded = Math.round(output*1000)/1000;
    return rounded.toString();
}

function Calculator(props){
	const [temperature, setTemperature] = useState('');
    const [scale, setScale] = useState('c');
    
    const handleCelsiusChange = (temperature) => {
    	setTemperature(temperature);
        setScale('c');
    }
    const handleFahrenheitChange = (temperature) => {
    	setTemperature(temperature);
        setScale('f');
    }
    
    const celsius = scale === 'f' ? tryConvert(temperature, toCelsius) : temperature;
    const fahrenheit = scale === 'c' ? tryConvert(temperature, toFahrenheit) : temperature;
    
    return(
    	<div>
        	<TemperatureInput scale="c" temperature={celsius} onTemperatureChange={handleCelsiusChange} />
            <TemperatureInput scale="f" temperature={fahrenheit} onTemperatureChange={handleFahrenheitChange}/>
        	<BoilingVerdict  celsius={parseFloat(celsius)} />
        </div>
    );
}

export default Calculator;

Calculator.jsx

 

(index.js 생략)

 

값을 입력하면 다른 빈 칸도 같이 변환되서 입력되는 걸 확인할 수 있다.

 

 

이 부분은 좀 난해한 느낌인지라 프로젝트를 하면서 알아가는 수 밖에 없을 것 같다.