오늘 수업시간에 한 틱택토 게임 함수형 Hooks API 써서 만들기 연습 !
useReducer 함수를 따로 빼는 것과 useEffect 부분 이 아직 안익숙하다. 일단 연습은 계속 해보기 !
오늘 처음 본(?)
useEffect
useEffect(()=>{}) 을 사용해서 리액트에게 컴포넌트가 렌더링 이후에 어떤 일을 수행해야하는 지 말함. 리액트는 우리가 넘긴 함수를 기억했다가 (요 함수가 'effect'라고 불림) DOM 업데이트 수행 수 불러낸다.
useEffect를 꼭 컴포넌트 안에서 불러내는 이유는 ? -> 내부 state 상태 변수들, props 들에게 접근할 수 있게 된다. 함수 범위 안에 있어서 API 없이 값을 얻을 수 있기 때문 !
useEffect는 최초 렌더링에 실행되고 이후 모든 업데이트에서 수행된다. 만약 특정 기준을 만들고 싶으면
useEffect( 첫 번째 인자 : 함수 ()=>{} , ___두 번재 인자 [] ___) 에 기준이되는 상태값을 넣어주면 된다. 오늘 연습할 때 요 두 번째 인자는 state.xIsNext 로 false < -> true 클릭 눌릴 때마다 바뀌었는데 변화가 있을 때마다 useEffect안의 코드가 실행되었다.
<오늘 useEffect 사용한 부분 >
const defaultState={
squares:Array(9).fill(null),
xIsNext:false,
winner:null,
}
const Game = () => {
const [state,dispatch] =React.useReducer(reducer, defaultState)
const handleClick=(n)=>{
if(state.squares[n]) return;
if(state.winner) return;
dispatch({type:'NEXT', index:n})
}
React.useEffect(()=>{
let win = Winner(state.squares)
console.log(win)
if(win){
console.log(win)
dispatch({type:'win', winner:win})
}
},[state.xIsNext])
useEffect는 const Game component 안에 있다. 실행 코드들 중 상태인 squares에 접근하고 있다 요 부분떄문에 useEffect는 컴포넌트 안에 넣기 ! 그리고 두 번째 인자가 state.xIsNext로 또한 상태값 에 바로 접근하고 있다.
App.jsx
import React,{Component} from 'react';
import Game from './components/game/Game'
const App=()=>{
return(
<>
<Game/>
</>
)
}
export default App
Game.jsx
import React from 'react'
import Board from './Board'
import Styled from 'styled-components'
const BoardDiv = Styled.div`
display:flex;
flex-wrap:wrap;
align-item:center;
justify-content:center;
width:300px;
`
const Winner =(squares)=>{
let lines =[
[0,1,2],
[3,4,5],
[6,7,8],
[0,3,6],
[1,4,7],
[2,5,8],
[0,4,8],
[2,4,6]
]
for (let i=0; i<lines.length; i++){
let [a,b,c] = lines[i]
if(squares[a] && squares[a] === squares[b] && squares[a]===squares[c]){
return squares[a]
}
}
return false
}
const reducer=(state,action)=>{
switch(action.type){
case 'NEXT':
let {squares} = {...state}
squares[action.index] = state.xIsNext ? 'X':'O'
return{
...state,
xIsNext:!state.xIsNext,
squares,
}
case 'win':
return{
...state,
winner : action.winner
}
}
}
const defaultState={
squares:Array(9).fill(null),
xIsNext:false,
winner:null,
}
const Game = () => {
const [state,dispatch] =React.useReducer(reducer, defaultState)
const handleClick=(n)=>{
if(state.squares[n]) return;
if(state.winner) return;
dispatch({type:'NEXT', index:n})
}
React.useEffect(()=>{
let win = Winner(state.squares)
console.log(win)
if(win){
console.log(win)
dispatch({type:'win', winner:win})
}
},[state.xIsNext])
return(
<>
{state.winner ? `${state.winner}님 승리!` : `Next player is ${state.xIsNext ? 'X' :'O' }`}
<BoardDiv>
<Board onClick={handleClick} squares = {state.squares}/>
</BoardDiv>
</>
)
}
export default Game
Board.jsx
import React from 'react'
import Square from './Square'
const Board =({onClick, squares})=>{
const square = squares.map((v,i)=>{
return(
<>
<Square onClick={()=>onClick(i)} key={i} value={v}/>
</>
)
})
return square
}
export default Board
Square.jsx
import React from 'react'
import Styled from 'styled-components'
const Button = Styled.button`
width:33.333%;
height:70px;
border:1px solid #000;
background:#fff;
cursor:pointer;
font-size:30px;
`
const Square =({onClick, value})=>{
return(
<>
<Button onClick={()=>onClick()}>{value}</Button>
</>
)
}
export default Square
'React + React Native + Expo' 카테고리의 다른 글
[React] 리액트 CRUD (0) | 2021.07.31 |
---|---|
[React native] 기초 다지기 - view / 버튼 / Image / flex 세로 가로 설정 / 정렬 등 CSS (0) | 2021.07.30 |
[React 연습 4일차] 리액트 TicTacToe Game 구현 (0) | 2021.07.05 |
[React 연습 3일차] 리액트 TicTacToe Game 구현 (0) | 2021.07.05 |
[React 연습 2일차] 리액트 TicTacToe Game 구현 (0) | 2021.06.30 |