JSX에서 js의 for문과 if문을 사용하지 못하는 것은 아니지만 코드가 지져분해져 많이 사용되진 않지만 사용법을 알려주시니 기억은 하고 있자..

 

if문 사용하기

if문을 사용하는 방법은 함수를 사용하는 방법이다. jsx에서 { } 를 사용하면 js문법을 사용할 수 있는데 거기에 즉시실행함수를 실행하고 해당 함수 내부에 if문을 사용하면 된다.

    return(
        <>
            ...
            {(()=>{
                if(result.length === 1){
                    return null;
                }else{
                    return <>
                        <div>{result.length}</div>
                    </>
                }
            })()}
            
            ....
		</>
    )

 

 

for문 사용하기

for문도 if문과 동일하다. 함수안에 넣으면 사용하기 그나마 간편해진다. (함수는 즉시실행함수여야한다.)

return (			
		...
            {
                //반복문
                (()=>{
                    const array = [];
                    for(let i =0; i<5; i++){
                        array.push(<div>안녕하신가</div>);
                    }
                    return array;
                })()
            }
        ...
            
)

 

JSX에서 배열을 반환하는 것.

jsx에서 배열을 반환해도 된다. 하지만 실무나 연습할 때 좀 처럼 사용되진 않는다고 하셨다. apple coding 강의볼 때 탭구현할 때 본거 같기도하다.

return [
	<div key="apple">사과</div>
    <div key="AsianPear">배</div>
    <div key="banana">바나나</div>
    <div key="mandarin">귤</div>
]

 

 

 

전체코드

import React, {useRef, useState} from "react";
import response from "./Response";

const ResponseHooks = () => {
    const [state,setState] = useState('waiting');
    const [message, setMessage] = useState('클릭해서 시작하세요.');
    const [result, setResult] = useState([]);
    const timer = useRef(null);
    const startTime = useRef(0);

    const onClickScreen = () => {
        if(state === 'waiting'){
            setState('ready');
            setMessage('색이 바뀌면 클릭해주세요');
            const max = 2000; //2초
            const min = 500 // 0.5초
            const randTime = Math.floor(Math.random() * (max - min + 1)) + min;
            timer.current = setTimeout(()=>{
                startTime.current = new Date().getTime();
                setState('now');
                setMessage('클릭해주세요!!');
            },randTime);
        }else if(state === 'ready'){
            alert('너무 성급합니다. 다시 시작하겠습니다.');
            setState('waiting');
            setMessage('클릭해서 시작하세요.');
            clearTimeout(timer.current);
        }else if(state === 'now'){
            clearTimeout(timer.current);
            const endTime = new Date().getTime();
            const responseTime = endTime - startTime.current;
            setMessage('클릭해서 시작하세요.');
            setState('waiting');
            setResult((prev) => {
                return [...prev, responseTime];
            });
        }

    }

    const onResetClick = () => {
        setResult([]);
    }

    const renderAverage = () => {
        return result.length === 0 ?
            null:
            <>
                <div>평균 시간{result.reduce((a,c)=>a+c) / result.length }ms</div>
                <button onClick={onResetClick}>리셋</button>
            </>
    }

    return(
        <>
            <div
                id="screen"
                className={state}
                onClick={onClickScreen}
            >
                {message}
            </div>
            {(()=>{
                if(result.length === 1){
                    return null;
                }else{
                    return <>
                        <div>{result.length}</div>
                    </>
                }
            })()}

            {
                //반복문
                (()=>{
                    const array = [];
                    for(let i =0; i<5; i++){
                        array.push(<div>안녕하신가</div>);
                    }
                    return array;
                })()
            }
            {renderAverage()}
        </>
    )
}

export default ResponseHooks;

강의를 보지않고 혼자서 hooks로 전환했을 때는 버그가 있었다. setTimeout이 제대로 취소되지 않았고, startTime이 제대로 설정되지 않아서 평균 반응속도가 이상하게 나오는 현상이 발생했다. 

강의를 보고 이유를 알아보니 React Hooks에서 값이 바뀌는 부분은 그냥 사용하면 안되고 useRef를 사용해야한다는 것을 새롭게 알게 되었다.

useRef vs useState

useRef와 useState의 차이 : 렌더링의 차이가 있다.

useRef는 값이 바뀌어도 렌더링이 안되지만 useState는 값이 바뀌면 리렌더링이 발생한다.

 

useRef 사용처 2가지

1. useRef는 DOM을 넣는거 말고 다른 방식으로 사용되는게 값이 바뀌기는 하지만 화면에 영향을 끼치고 싶지는 않을 때 사용한다.

2. DOM을 넣어두고 DOM을 직접 제어하고 싶을 때 사용

 

※ useRef는 current써주는것에 주의해야한다.

 

import React, {useRef, useState} from "react";
import response from "./Response";

const ResponseHooks = () => {
    const [state,setState] = useState('waiting');
    const [message, setMessage] = useState('클릭해서 시작하세요.');
    const [result, setResult] = useState([]);
    const timer = useRef(null);
    const startTime = useRef(0);

    const onClickScreen = () => {
        if(state === 'waiting'){
            setState('ready');
            setMessage('색이 바뀌면 클릭해주세요');
            const max = 2000; //2초
            const min = 500 // 0.5초
            const randTime = Math.floor(Math.random() * (max - min + 1)) + min;
            timer.current = setTimeout(()=>{
                startTime.current = new Date().getTime();
                setState('now');
                setMessage('클릭해주세요!!');
            },randTime);
        }else if(state === 'ready'){
            alert('너무 성급합니다. 다시 시작하겠습니다.');
            setState('waiting');
            setMessage('클릭해서 시작하세요.');
            clearTimeout(timer.current);
        }else if(state === 'now'){
            clearTimeout(timer.current);
            const endTime = new Date().getTime();
            const responseTime = endTime - startTime.current;
            setMessage('클릭해서 시작하세요.');
            setState('waiting');
            setResult((prev) => {
                return [...prev, responseTime];
            });
        }

    }

    const onResetClick = () => {
        setResult([]);
    }

    const renderAverage = () => {
        return result.length === 0 ?
            null:
            <>
                <div>평균 시간{result.reduce((a,c)=>a+c) / result.length }ms</div>
                <button onClick={onResetClick}>리셋</button>
            </>
    }

    return(
        <>
            <div
                id="screen"
                className={state}
                onClick={onClickScreen}
            >
                {message}
            </div>
            {renderAverage()}
        </>
    )
}

export default ResponseHooks;

hooks로 변환된 ResponseHooks.jsx 전체코드

반응속도체크 코딩

전체코드

import React, {Component} from "react";

class Response extends Component{
    state = {
        state:'waiting',
        message:'클릭해서 시작하세요.',
        result:[],
    }
    timer = null;
    startTime = 0;

    onClickScreen = e => {
        const {state, message, result} = this.state;
        const {target} = e;
        if(state === 'waiting'){ //기달 -> 준비
            this.setState({state:'ready', message:'색이 바뀌면 클릭해주세요'});
            const max = 2000; //2초
            const min = 500 // 0.5초
            const randTime = Math.floor(Math.random() * (max - min + 1)) + min;
            this.timer = setTimeout(()=>{
                this.setState({state:'now', message:'클릭해주세요!'});
                this.startTime = new Date().getTime();
            },randTime);
        }else if(state === 'ready'){
            //너무 성급하다 다시 시작하겠다 멘트
            alert('너무 성급합니다. 다시 시작하겠습니다.');
            this.setState({state:'waiting', message:'클릭해서 시작하세요.'});
            clearTimeout(this.timer);
        }else if(state === 'now'){
            const endTime = new Date().getTime();
            clearTimeout(this.timer);
            const responseTime = endTime - this.startTime;
            this.setState((prevState) => {
                return {result:[...prevState.result, responseTime], state:'waiting', message: '클릭해서 시작하세요.'}
            });
        }
    }

    renderAverage = () => {
        const {result} = this.state;
        return result.length === 0 ?
            null:
            <div>평균 시간{this.state.result.reduce((a,c)=>a+c) / this.state.result.length }ms</div>
    }

    render() {
        const {state, message, result} = this.state;
        return (
            <>
                <div
                    id="screen"
                    className={state}
                    onClick={this.onClickScreen}
                >
                    {message}
                </div>
                {this.renderAverage()}
                {
                    result.map(v => <div>{v}ms</div>)
                }
            </>
        );
    }
}

export default Response;

강의 보기 전에 미리 코딩해봄. 그래서 강의랑 좀 다름.

 

※ setTimeout은 call stack으로 넘어가서 실행이 되는데 콜스택으로 넘어가더라도 clearTimeout으로 취소 가능함.

+ Recent posts