[ToyProject-Todomate] ํˆฌ๋‘๋ฉ”์ดํŠธ ํด๋ก  ํ”„๋กœ์ ํŠธ 21

2022. 1. 4. 00:05ใ†WEB Dev/ToyProject

728x90


๐Ÿ”ท CloneTodo โ˜‘ - Todomate Clone Project  |  Team CloneMate

 

CloneTodo : ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ์‚ฌ๋ž‘ํ•˜๋Š” ํˆฌ๋‘๋ฉ”์ดํŠธ๋ฅผ ํด๋ก ํ•˜์—ฌ ์›น ์„œ๋น„์Šค๋ฅผ ๋ฐฐํฌํ•ด๋ณด๋Š” ํ”„๋กœ์ ํŠธ

 


 

์ด์ œ๋Š” + ๋ชจ์–‘ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ๋ฆฌ์ŠคํŠธ๊ฐ€ ์ถ”๊ฐ€๋˜์–ด์•ผ ํ•œ๋‹ค. ์ด๊ฒƒ๋„ ๊น€๋‹ค์ •๋‹˜์˜ ์ฑ…์„ ์ฐธ๊ณ ํ•ด์„œ ์ผ๋ถ€๋ถ„ ๋ณ€ํ˜•ํ•ด์„œ ๊ตฌํ˜„ํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค.

 

 

 

์ง€๊ธˆ ๋ฌธ์ œ๋Š” ์›๋ž˜ todomate์˜ ์ถ”๊ฐ€ ๋ฒ„ํŠผ์ด ์ƒ๋‹จ ๋ฐ” ์˜ค๋ฅธ์ชฝ์— ์žˆ์–ด์„œ ๋‚˜๋„ ๊ทธ๋ ‡๊ฒŒ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค๋ฉด, route ๋ณ„๋กœ BasicNavBar๊ฐ€ ๋‹ค๋ฅด๊ฒŒ ๋ณด์ผ ์ˆ˜ ์žˆ๋„๋ก ํ•ด์•ผํ•˜๋Š”๊ฑด์ง€, ์•„๋‹ˆ๋ฉด ๊ทธ๋ƒฅ ํ™”๋ฉด์— ๊ตฌํ˜„ํ•˜๊ณ  ์œ„์น˜๋งŒ ์ƒ๋‹จ์œผ๋กœ ์˜ฎ๊ฒจ๋†”๋„ ๋˜๋Š”์ง€ ์ด๋‹ค. 

๊ณ ๋ฏผํ•˜๋‹ค๊ฐ€ ์ผ๋‹จ ๋ฒ„ํŠผ์„ ๋งŒ๋“ค์–ด์„œ ์ƒ๋‹จ์— ์˜ฌ๋ ค๋†“๊ณ , ๋‚˜์ค‘์— ์กฐ๊ฑด๋ฌธ์„ ์“ฐ๋˜ ๋ญ˜ ํ•˜๋˜ ํ•ด์•ผ๊ฒ ๋‹ค๊ณ  ์ƒ๊ฐ...

 

 

 

1. Todo๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ ๋งŒ๋“ค๊ธฐ

 

์ฑ…์—์„œ๋Š” todo ์ถ”๊ฐ€๋ฅผ ์œ„ํ•œ UI์™€ ๋ฐฑ์—”๋“œ๋ฅผ ์ฝœํ•  ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•˜๋Š”๋ฐ ์ด ํ•จ์ˆ˜๋Š” ๊ฐ€์งœ(Mock) ํ•จ์ˆ˜๊ณ , todo๋ฅผ ์ถ”๊ฐ€ํ•  ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜์™€ ํ•จ์ˆ˜๋ฅผ UI์— ์—ฐ๊ฒฐํ•˜๋Š” ๊ฒƒ์„ ํ•˜๋‚˜์˜ ์ฑ•ํ„ฐ๋กœ ์‚ผ์•˜๋‹ค.

๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์ง„ํ–‰ํ•ด๋ณด์ž.

 

์šฐ์„  UI๋ฅผ ์œ„ํ•ด GoalForm (์ฑ…์—์„œ๋Š” AddTodo) ์ด๋ผ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค์–ด์ค€๋‹ค.๋ณ„๋„์˜ ํŒŒ์ผ๋กœ ์ƒ์„ฑํ•œ๋‹ค.

useState๋ฅผ ์ด์šฉํ•ด ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ๊ฐ’์„ ๋ฐ›์„ ๊ฐ์ฒด๋ฅผ ๋ฏธ๋ฆฌ ์ƒ์„ฑํ•ด์ค€๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์•„๋ž˜ MUI๋ฅผ ์ด์šฉํ•ด UI๋ฅผ ๋””์ž์ธ ํ•˜๋ฉด ๋˜๋Š”๋ฐ, ์—ฌ๊ธฐ์„œ ๋งŒ๋“œ๋Š” + ๋ฒ„ํŠผ์€ '์ž…๋ ฅ'์„ ํ•ด์ฃผ๋Š” ๋ฒ„ํŠผ์ด๊ธฐ ๋•Œ๋ฌธ์— ์šฐ๋ฆฌ ํ™”๋ฉด์—์„œ๋Š” 'ํ™•์ธ' ์ด๋ผ๋Š” ํ…์ŠคํŠธ ๋ฒ„ํŠผ์œผ๋กœ ๋Œ€์ฒดํ•œ๋‹ค.

 

 

 

import { Button, Grid, Box, TextField } from "@mui/material";
import React, { useState } from "react";


export default function GoalForm(){

    let [goalTodo, goalTodoChange] = useState({ title : '' });



    return(
        <Box style={{ margin : 16, padding: 16, position:'relative' }}>
            <Grid container>
                <Grid xs={11} md={11} item style={{paddingRight: 12}}>
                    <p className="goalform_title" style={{fontSize: '12px', color: '#aeaeae'}}>์ œ๋ชฉ</p>
                    <TextField fullWidth id="goalform_textfield" variant="standard" /> 
                </Grid>
                <Grid xs={1} md={1} item >
                    <Button fullWidth color="secondary" style={{position:'relative', 
                    top: '-85px',  fontSize: '14px', fontWeight: '600', color: '#111'}} >
                        ํ™•์ธ
                    </Button>    
                </Grid>
            </Grid>
        </Box>
    )

}

 

 

์ด๋ ‡๊ฒŒ ๋งŒ๋“  GoalForm ์ปดํฌ๋„ŒํŠธ๋ฅผ Goals ์ปดํฌ๋„ŒํŠธ์— ์ถ”๊ฐ€ํ•ด์ค€๋‹ค. (๋‚˜์ค‘์— ์ƒ๋‹จ + ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์œ„์— ๋ ˆ์ด์–ด์ฒ˜๋Ÿผ ๋œจ๋„๋ก ๋งŒ๋“ค์–ด๋ณด์ž)

 

 

 

 

2. Add ํ•ธ๋“ค๋Ÿฌ ์ถ”๊ฐ€

 

๋ฆฌ์•กํŠธ๋กœ ๋ญ”๊ฐ€๋ฅผ ๋งŒ๋“ค๋•Œ๋Š” ์ด๋ฒคํŠธ๋ฅผ '๊ฐ์ง€'ํ•˜๊ณ  ๊ทธ๊ฒƒ์„ ์ „์†กํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค.

๊ทธ๋ž˜์„œ ํ‚ค๋ณด๋“œ๋กœ TextField์— ๋ญ”๊ฐ€๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ์‹คํ–‰ํ•  ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์™€, ํ™•์ธ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๋•Œ ๋ฐœ์ƒํ•  ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ํ•„์š”ํ•˜๋‹ค. ์ฑ…์—์„œ๋Š” ์ด ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋“ค ํ•จ์ˆ˜์˜ ์ด๋ฆ„์„ ์ œ๊ณตํ•ด์ฃผ๋Š”๋ฐ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

 

- onInputChange : ์‚ฌ์šฉ์ž๊ฐ€ TextField์— ๋ฌธ์ž์—ด์„ ์ถ”๊ฐ€ํ•˜๋ฉด ํ•ด๋‹น ๋ฌธ์ž์—ด์„ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐ์ฒด๋กœ ์ €์žฅํ•œ๋‹ค.

- onButtonClick : ์‚ฌ์šฉ์ž๊ฐ€ ํ™•์ธ(์ฑ…์—์„œ๋Š” +)๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๋•Œ ์‹คํ–‰๋˜๊ณ , onInputChange์—์„œ ์ €์žฅํ•œ ๋ฌธ์ž์—ด์„ ๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€ํ•œ๋‹ค.

- enterKeyEventHandler : onButtonClick๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ์ด์ง€๋งŒ ์—”ํ„ฐ๋‚˜ ๋ฆฌํ„ด์„ ๋ˆŒ๋ €์„ ๋•Œ๋„ ์‹คํ–‰๋˜๋„๋ก ํ•˜๋Š” ํ•จ์ˆ˜๋‹ค.

 

 

 

์ดˆ๋ฐ˜์— useState๋กœ ๋งŒ๋“  goalTodo๋Š” ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ๊ฐ’์„ ์ž„์‹œ๋กœ ์ €์žฅํ•˜๋Š” ๊ณณ์ด๋‹ค. TextField์—์„œ ๊ฐ’์ด ์ž…๋ ฅ๋˜๋ฉด onChange๋ฅผ props๋กœ ์“ธ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด onChange๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ํ‚ค๋ณด๋“œ๋ฅผ ๋ˆ„๋ฅผ ๋•Œ ๋งˆ๋‹ค ์‹คํ–‰๋œ๋‹ค.

๋”ฐ๋ผ์„œ onChange์— ํ•ธ๋“ค๋Ÿฌ์ธ onInputChange๋ฅผ ์—ฐ๊ฒฐํ•˜๋ฉด ์‚ฌ์šฉ์ž ์ž…๋ ฅ ์ •๋ณด๋ฅผ ๊ฐ์ฒด์— ์ €์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๋ฒคํŠธ์˜ ๊ฐ’์ธ e.target.value๋ฅผ title์˜ '' ์— ๋Œ€์ฒดํ•ด์ฃผ๋Š” ํ•จ์ˆ˜๋ฅผ ์ ์–ด๋ณด์ž.

๋ณ€์ˆ˜ thisGoal ์€ state์ธ goalTodo์˜ item์ด ํ• ๋‹น๋œ๋‹ค. state๋Š” ๋ฐ”๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ์›๋ณธ ๊ฐ’์€ ๊ทธ๋Œ€๋กœ ๋‘๊ณ  ๊ทธ๊ฒƒ์„ ์นดํ”ผํ•ด์„œ ๋ณ€์ˆ˜๋ฅผ ํ•˜๋‚˜ ํ• ๋‹นํ•ด์•ผ ํ•œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  thisGoal์˜ title์€ TextField์˜ ๊ฐ’์ธ e.target.value ์œผ๋กœ ๋ฐ”๊ฟ”์ค€๋‹ค. 

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์›๋ณธ์€ ๊ทธ๋Œ€๋กœ ์‚ด์•„์žˆ๊ณ , thisGoal์ด๋ผ๋Š” ๋ณ€์ˆ˜๋Š” {{ title: e.target.value }} ๊ฐ€ ๋œ๋‹ค.

state๋ฅผ ์ด๊ฒƒ์œผ๋กœ ๋ฐ”๊ฟ”์น˜๊ธฐ ํ•ด์•ผ ํ•˜๋Š”๋ฐ, useState์ด๊ธฐ ๋•Œ๋ฌธ์— goalTodoChange๋ผ๋Š” ๋ฏธ๋ฆฌ ์ƒ์„ฑ๋œ useState์˜ ๋ณ€๊ฒฝํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•œ๋‹ค.

 

 

 

import { Button, Grid, Box, TextField } from "@mui/material";
import React, { useState } from "react";


export default function GoalForm(){

    let [goalTodo, goalTodoChange] = useState({item : { title : '' }});

    function onInputChange(e) {
        const thisGoal = goalTodo.item;
        thisGoal.title = e.target.value;
        goalTodoChange({item : thisGoal})
        console.log(thisGoal)
    }

    return(
        <Box style={{ margin : 16, padding: 16, position:'relative' }}>
            <Grid container>
                <Grid xs={11} md={11} item style={{paddingRight: 12}}>
                    <p className="goalform_title" style={{fontSize: '12px', color: '#aeaeae'}}>์ œ๋ชฉ</p>
                    <TextField fullWidth id="goalform_textfield" variant="standard"
                    onChange={onInputChange} /> 
                </Grid>
                <Grid xs={1} md={1} item >
                    <Button fullWidth color="secondary" style={{position:'relative',
                    top: '-85px',  fontSize: '14px', fontWeight: '600', color: '#111'}} >
                        ํ™•์ธ
                    </Button>    
                </Grid>
            </Grid>
        </Box>
    )

}

 

 

 

3. Add ํ•จ์ˆ˜ ์ž‘์„ฑ

 

 

์ด์ œ ํ™•์ธ์„ ๋ˆ„๋ฅด๋ฉด ์ž‘์„ฑํ•œ ๋ชฉํ‘œ๊ฐ€ ์ถ”๊ฐ€๋˜์–ด์•ผ ํ•œ๋‹ค. 

์ด ๋•Œ๋Š” ํ™•์ธ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๊ฒŒ ๋˜๋ฉด onButtonClick์ด๋‚˜ enterKeyEventHandler์ด ์‹คํ–‰๋˜๊ฒŒ ํ•œ๋‹ค. ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜๋ฉด App.js์— ๋งŒ๋“ค์–ด๋‘” goal State์— ๋‚ด์šฉ์ด ์ถ”๊ฐ€๋˜๋„๋ก ํ•ด์ค€๋‹ค.

์—ฌ๊ธฐ์„œ ๋ฌธ์ œ๋Š” ์–ด์ œ ํ™•์ธํ•œ ๋ฐ”์™€ ๊ฐ™์ด props๋Š” ์•„๋ž˜์—์„œ ์œ„๋กœ ๋ชป ์˜ฌ๋ผ๊ฐ„๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์—…๋ฐ์ดํŠธ ํ•  State๊ฐ€ ์žˆ๋Š” App.js์— ๋ฆฌ์ŠคํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค. 

๊ทธ๋ฆฌ๊ณ  ๊ทธ ํ•จ์ˆ˜๋ฅผ props๋กœ GoalForm ์ปดํฌ๋„ŒํŠธ์— ๋„˜๊ฒจ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

 

 

App.js์—์„œ ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•ด๋ณธ๋‹ค.

์•„๊นŒ onInputChange์™€ ๊ฐ™๋‹ค. ์›๋ณธ state์ธ goal.items์„ thisItems ๋ผ๋Š” ๋ณ€์ˆ˜์— ์นดํ”ผํ•œ๋‹ค. (์›๋ž˜ items๋ผ๋Š” ์ด๋ฆ„์„ ์•ˆ ๋ถ™์˜€๋Š”๋ฐ, ์ฑ…๊ณผ ๋‚ด์šฉ์„ ๋งž์ถ”๊ธฐ ์œ„ํ•ด ์—…๋ฐ์ดํŠธ ํ–ˆ์Œ!)

๊ทธ๋ฆฌ๊ณ  item์˜ id๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๊ณ , done์„ false๋กœ ๋งŒ๋“ค์–ด์ค€๋‹ค. ์ด๊ฒƒ์„ ์•„๊นŒ ์นดํ”ผํ•œ thisItems๋ผ๋Š” ๋ณ€์ˆ˜์— push๋กœ ๋ฐ€์–ด๋„ฃ์–ด์ฃผ๊ณ  ์ด๊ฒƒ์„ goalChange๋ผ๋Š” ๋ณ€๊ฒฝํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ์›๋ณธ state๋ฅผ ๋ฐ”๊ฟ”์ค€๋‹ค.

 

 

 

  // ๋ชฉํ‘œgoals ํŽ˜์ด์ง€ goal ์•„์ดํ…œ
  let [goal, goalChange] = useState(
     { items: [{
            id : 0,
            title: '๋ชฉํ‘œ ๋งŒ๋“ค๊ธฐ',
            done: true
          },
          {
            id: 1,
            title: '๋ชฉํ‘œ ๋งŒ๋“ค๊ธฐ 2',
            done: false
          },
          {
            id: 2,
            title: '๋ชฉํ‘œ ๋งŒ๋“ค๊ธฐ 3',
            done: false
          }]
    
    }
  )

  function add(item){

    const thisItems = goal.items; // goal State ์›๋ณธ ์นดํ”ผ
    item.id = 'ID-' + thisItems.length; //key๋ฅผ ์œ„ํ•œ id ์ถ”๊ฐ€
    item.done = false; // done false๋กœ ์ดˆ๊ธฐํ™”
    thisItems.push(item) // ์นดํ”ผํ•œ goal ๋ฆฌ์ŠคํŠธ์— ์•„์ดํ…œ ์ถ”๊ฐ€
    goalChange({items: thisItems}); //goalChange๋ฅผ ์ด์šฉํ•ด state ๋ณ€๊ฒฝ
    console.log('items :', goal.items)

  }

 

 

 

๊ทธ๋ฆฌ๊ณ  ์ด add ํ•จ์ˆ˜๋ฅผ props๋กœ ๋ณด๋‚ธ๋‹ค. 

 

 

 

import React, { useState } from "react";
import "../stylesheets/App.css";
import { Button  } from "@mui/material";
import { ThemeProvider, createTheme } from "@mui/material/styles";
import { Switch, Route, useHistory } from "react-router-dom";
import Signin from "./Signin";
import Join from "./Join";
import BasicNavBar from "./BasicNavBar";
import Goals from "./Goals";
import Main from "./Main";


function App() {
  let history = useHistory();

  // ๋ชฉํ‘œgoals ํŽ˜์ด์ง€ goal ์•„์ดํ…œ
  let [goal, goalChange] = useState(
     { items: [{
            id : 0,
            title: '๋ชฉํ‘œ ๋งŒ๋“ค๊ธฐ',
            done: true
          },
          {
            id: 1,
            title: '๋ชฉํ‘œ ๋งŒ๋“ค๊ธฐ 2',
            done: false
          },
          {
            id: 2,
            title: '๋ชฉํ‘œ ๋งŒ๋“ค๊ธฐ 3',
            done: false
          }]
    
    }
  )

  function add(item){

    const thisItems = goal.items; // goal State ์›๋ณธ ์นดํ”ผ
    item.id = 'ID-' + thisItems.length; //key๋ฅผ ์œ„ํ•œ id ์ถ”๊ฐ€
    item.done = false; // done false๋กœ ์ดˆ๊ธฐํ™”
    thisItems.push(item) // ์นดํ”ผํ•œ goal ๋ฆฌ์ŠคํŠธ์— ์•„์ดํ…œ ์ถ”๊ฐ€
    goalChange({items: thisItems}); //goalChange๋ฅผ ์ด์šฉํ•ด state ๋ณ€๊ฒฝ
    console.log('items :', goal.items)

  }


  return (
    <ThemeProvider theme={theme}>
      <Switch>
        <Route exact path="/">
          <div className="App">
            <div className="header">
              <img className="main_img" src="images/todomate.jpg" />
              <h1>todo mate</h1>
              <h3>ํ•  ์ผ์„ ์ž‘์„ฑ, ๊ณ„ํš, ๊ด€๋ฆฌํ•˜์„ธ์š”.</h3>
            </div>
            <div className="start_btn">
              <Button 
                className="join_btn" 
                color="btn"
                variant="contained" 
                sx={{ boxShadow: 'none'}}
                onClick={() => {
                  history.push("/join");
                }}
              >
                ๊ฐ€์ž…ํ•˜๊ธฐ
              </Button>
              <Button
                className="signin_btn"
                color="btn"
                variant="contained"
                sx={{ boxShadow: 'none'}}
                onClick={() => {
                  history.push("/signin");
                }}
              >
                ๋กœ๊ทธ์ธ
              </Button>
            </div>
          </div>
        </Route>
        <Route exact path="/main">
          <Main/>
        </Route>
        <Route exact path="/join">
        <BasicNavBar/>
          <Join />
        </Route>
        <Route exact path="/signin">
        <BasicNavBar/>
          <Signin />
        </Route>
        <Route exact path="/goals">
        <BasicNavBar/>
          <Goals goal={goal.items} add={add} key={goal.items.id} />
        </Route>
        </Switch>
    </ThemeProvider>
  );
}

export default App;

 

 

 

์—ฌ๊ธฐ์„œ ๋ฌธ์ œ๋Š” ๋‚˜๋Š” App.js -> Goals.js -> GoalForm.js ๋กœ ๋„ฃ์–ด์ค˜์•ผ ํ•ด์„œ ํ•œ ๋ฒˆ ๋” props๋กœ ์ „๋‹ฌํ•œ๋‹ค.

 

 

import React from "react";
import { Checkbox, InputBase, ListItem, ListItemText } from "@mui/material";
import GoalForm from "./GoalForm";

export default function Goals(props) {
  console.log(props.goal);
  let goalItems = props.goal;
  let add = props.add;
  return (
    <>
    <GoalForm add={add} />

        {
        goalItems.map((item, idx) => {
        return (
                <ListItem className="goals-wrap">
                    <Checkbox checked={item.done} />
                    <ListItemText>
                    <InputBase
                        inputProps={{ "aria-label": "naked" }}
                        type="text"
                        id={item.id}
                        name={item.id}
                        value={item.title}
                        multiline={true}
                        fullWidth={true}
                    />
                    </ListItemText>
                </ListItem>
                );
            })
        }
    </>
  );
}

 

 

 

๊ทธ๋ฆฌ๊ณ  ์ด add ํ•จ์ˆ˜๋ฅผ onButtonClick ์˜ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜๋กœ ์‚ฌ์šฉํ•œ๋‹ค. 

 

import { Button, Grid, Box, TextField } from "@mui/material";
import React, { useState } from "react";


export default function GoalForm(props){

    let [goalTodo, goalTodoChange] = useState({item : { title : '' }}, props.add);

    function onInputChange(e) {
        const thisGoal = goalTodo.item;
        thisGoal.title = e.target.value;
        goalTodoChange({item : thisGoal})
        console.log(thisGoal)
    }

    function onButtonClick(){
        props.add(goalTodo.item);
        goalTodoChange({item : {title: ''}});
    }

    return(
        <Box style={{ margin : 16, padding: 16, position:'relative' }}>
            <Grid container>
                <Grid xs={11} md={11} item style={{paddingRight: 12}}>
                    <p className="goalform_title" style={{fontSize: '12px', color: '#aeaeae'}}>์ œ๋ชฉ</p>
                    <TextField fullWidth id="goalform_textfield"
                    variant="standard" onChange={onInputChange} /> 
                </Grid>
                <Grid xs={1} md={1} item >
                    <Button fullWidth color="secondary" onClick={onButtonClick}
                    style={{position:'relative', top: '-85px',  
                    fontSize: '14px', fontWeight: '600', color: '#111'}} >
                        ํ™•์ธ
                    </Button>    
                </Grid>
            </Grid>
        </Box>
    )

}

 

์šฐ์™• ๋Œ€๋ฐ• ์„ฑ๊ณตํ–ˆ๋‹ค ใ… ใ… 

 

 

 

 

๊ทธ๋Ÿผ ๋˜‘๊ฐ™์ด ์—”ํ„ฐํ‚ค๋กœ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋„๋ก enterKeyEventHandler ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค. ๊ธฐ๋Šฅ์€ add ํ•จ์ˆ˜์™€ ๊ฐ™๊ธฐ ๋•Œ๋ฌธ์— key์ž…๋ ฅ๋งŒ ์ฒ˜๋ฆฌํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

 

 

GoalForm.js ์˜ onButtonClick ์•„๋ž˜์— ์ถ”๊ฐ€ํ•ด์ค€๋‹ค. 

 

function enterKeyEventHandler(e){
  if(e.key === 'Enter'){
	  onButtonClick();
  }
}

 

์ด enterKeyEventHandler ํ•จ์ˆ˜๋Š” TextField์˜ onKeyPress ์ด๋ฒคํŠธ์— ๋ฐ”์ธ๋”ฉํ•ด์ค€๋‹ค.

 

import { Button, Grid, Box, TextField } from "@mui/material";
import React, { useState } from "react";


export default function GoalForm(props){

    let [goalTodo, goalTodoChange] = useState({item : { title : '' }}, props.add);

    function onInputChange(e) {
        const thisGoal = goalTodo.item;
        thisGoal.title = e.target.value;
        goalTodoChange({item : thisGoal})
        console.log(thisGoal)
    }

    function onButtonClick(){
        props.add(goalTodo.item);
        goalTodoChange({item : {title: ''}});
    }

    
    function enterKeyEventHandler(e){
        if(e.key === 'Enter'){
            onButtonClick();
        }
    
      }



    return(
        <Box style={{ margin : 16, padding: 16, position:'relative' }}>
            <Grid container>
                <Grid xs={11} md={11} item style={{paddingRight: 12}}>
                    <p className="goalform_title" style={{fontSize: '12px', color: '#aeaeae'}}>์ œ๋ชฉ</p>
                    <TextField fullWidth id="goalform_textfield" variant="standard" onChange={onInputChange} /> 
                </Grid>
                <Grid xs={1} md={1} item >
                    <Button fullWidth color="secondary" onClick={onButtonClick} 
                    value={goalTodo.item.title} onKeyPress={enterKeyEventHandler}
                    style={{position:'relative', top: '-85px',  fontSize: '14px', fontWeight: '600', color: '#111'}} >
                        ํ™•์ธ
                    </Button>    
                </Grid>
            </Grid>
        </Box>
    )

}

 

 

 

๋‹ค ์ •์ƒ์ ์œผ๋กœ ํ•œ ๋“ฏ ์‹ถ์€๋ฐ ์™œ์ธ์ง€ ์—”ํ„ฐ๋กœ๋Š” ์ž…๋ ฅ์ด ์•ˆ๋˜๊ณ  ์žˆ๋‹ค.

์–ด์จŒ๋“  ์ถœ๋ ฅ์„ ์‹œํ‚ค๊ณ  ์žˆ์œผ๋‹ˆ !! ์˜ค๋Š˜์€ ์—ฌ๊ธฐ๊นŒ์ง€ ใ… ใ… 

728x90