ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [ToyProject-Todomate] ํˆฌ๋‘๋ฉ”์ดํŠธ ํด๋ก  ํ”„๋กœ์ ํŠธ 23
    WEB Dev/ToyProject 2022. 1. 6. 23:47
    728x90


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

     

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

     


     

    ์˜ค๋Š˜์€ ์ˆ˜์ •๋ถ€๋ถ„์„ ๋งŒ๋“ค ์ฐจ๋ก€! ์‹ค์ œ๋กœ ์ฑ…์—์„œ ๋„์›€์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„์€ ์„œ๋ฒ„ ์—ฐ๊ฒฐ์ด๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค.

    ์ฑ…์—์„œ๋Š” ์—„์ฒญ ๋‹จ์ˆœํ•œ ์•ฑ์„ ๋งŒ๋“ค๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค ใ… ใ… 

    ์–ด์จŒ๋“  ํˆฌ๋‘ ๋“ฑ๋ก, ์ˆ˜์ •, ์‚ญ์ œ๊ฐ€ ๊ธฐ๋Šฅ์˜ ๋Œ€๋ถ€๋ถ„์ด๋‹ˆ๊นŒ ...

     

     

    ์ˆ˜์ •์—๋Š” ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

    ์ฒซ๋ฒˆ์งธ๋Š” ํˆฌ๋‘ ์ƒํƒœ ๋ณ€ํ™”๋‹ค.

    ํˆฌ๋‘์— ์ฒดํฌ๋ฅผ ํ•˜๋ฉด ํ•  ์ผ์„ ์™„๋ฃŒํ•œ ์ƒํƒœ์ด๊ธฐ ๋•Œ๋ฌธ์— items state์˜ done ๊ฐ’์ด true๊ฐ€ ๋˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ๊ณผ

    ์ด๋ฏธ ๋“ฑ๋กํ•œ ํˆฌ๋‘๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

     

    ๊ทธ๋ฆฌ๊ณ  ๋˜ ํ•œ ๊ฐ€์ง€๋Š” ์ด๋ฏธ ๋“ฑ๋กํ•œ ํˆฌ๋‘๋ฅผ ํด๋ฆญํ•˜๋ฉด ๋‚ด์šฉ์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๋‹จ๊ณ„๋‹ค.

    ์ด ๋‹จ๊ณ„๊ฐ€ ์ข€ ๋ณต์žกํ•˜๋‹ค.

     

     

     

    ์šฐ์„  ๋“ฑ๋กํ•œ ๋ชฉํ‘œ์— readOnly ๋ผ๋Š” props๋กœ ์ƒํƒœ๋ฅผ ํ‘œํ˜„ํ•ด์ค˜์•ผ ํ•˜๋Š”๋ฐ, ์ฑ…์˜ ์ฝ”๋“œ๋ฅผ ํ•จ์ˆ˜ํ˜•์œผ๋กœ ์–ด๋–ป๊ฒŒ ๋ณ€ํ™˜ํ•ด์•ผ ํ•˜๋Š”์ง€ ๊ฐ์ด ์•ˆ์˜จ๋‹ค. 

     

      let goalItems = props.goal;
      let addGoal = props.addGoal;
      let deleteGoal = props.deleteGoal;
    
        function deleteEventHandler(e) {
          console.log( 'id : ',  e.target.id)
          deleteGoal(e.target.id, goalItems)
        }

     

     

    ์œ„์™€ ๊ฐ™์ด ๋งŒ๋“ค์–ด๋’€๋˜ props ๋“ค์ธ๋ฐ..

    ์ฑ…์—์„œ๋Š” 

     

     

    constructor(props) {
    	super(props)
        this.state = { item : props.item, readOnly : true };
        this.delete = props.delete;
    }

     

     

    ๊ทธ๋Ÿผ readOnly ๋ณ€์ˆ˜๋ฅผ ๋”ฐ๋กœ ์ค˜์•ผ ํ•˜๋Š”๊ฑด์ง€.. goalItems๋กœ ๋งŒ๋“  props ๋ฅผ ๊ฐ์ฒด๋กœ ๋งŒ๋“ค์–ด์•ผ ํ•˜๋Š”๊ฑด์ง€...

    ์™ ์ง€ ๋ณ„๋„๋กœ ๋ณ€์ˆ˜๋กœ ๋งŒ๋“ค์–ด ์ค˜์•ผ๊ฒ ์ง€..?

    ์•„๋‹ˆ state์— ์ถ”๊ฐ€ํ•ด๊ฐ€์ง€๊ณ  props๋กœ ๋งŒ๋“ค์–ด์ค˜์•ผํ•˜๋Š”๊ฑฐ๊ฒ ์ง€..?

    ์ด ์ •๋„ ๊ณต๋ถ€ํ–ˆ์œผ๋ฉด ์ฐฐ๋–ก๊ฐ™์ด ์•Œ์•„๋“ค์–ด์•ผํ•˜๋Š”๋ฐ...

     

     

    ์ €๋ฒˆ์— ๋งŒ๋“  goal state ์•„๋ž˜์— readOnly state๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.

     

     

      let [readOnly, readOnlyChange] = useState(true)

     

     

    ๊ทธ๋ฆฌ๊ณ  ๋‹ค์‹œ Goals ์ปดํฌ๋„ŒํŠธ๋กœ ๋„˜๊ฒจ์ฃผ์—ˆ๋‹ค.

     

     

    <Goals goal={goal.items} addGoal={addGoal} deleteGoal={deleteGoal} readOnly={readOnly}  />

     

     

    ๊ทธ๋ฆฌ๊ณ  offReadOnlyMode ๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์ค€๋‹ค.

     

     

       // readOnly ์ƒํƒœ ๋ณ€๊ฒฝ ํ•จ์ˆ˜
       function offReadOnlyMode(){
        console.log("Event!", readOnly)
        readOnlyChange(readOnly = false)
      }

     

     

    ์ด๊ฒƒ๋“ค์„ ๋˜ props๋กœ ๋‹ค ๋„˜๊ฒจ์ค€๋‹ค.

     

     

     

    <Goals goal={goal.items} addGoal={addGoal} 
    deleteGoal={deleteGoal} readOnly={readOnly} readOnlyChange={offReadOnlyMode}  />

     

     

    ๊ทธ๋ฆฌ๊ณ  Goals.js์—์„œ props๋กœ ๋ฐ›์•„์™€์„œ ๋ณ€์ˆ˜์— ๋‹ด๊ณ ...

     

      let readOnly = props.readOnly;
      let readOnlyChange = props.readOnlyChange;

     

    inputBase์— readOnly์™€ onClick ์ด๋ฒคํŠธ๋กœ ํ•จ์ˆ˜๋ฅผ ๋„˜๊ฒจ์ค€๋‹ค.

     

     

     <InputBase
       inputProps={{ "aria-label": "naked", readOnly: readOnly, }}
       onClick={readOnlyChange}
       type="text"
       id={item.id}
       name={item.id}
       value={item.title}
       multiline={true}
       fullWidth={true}
     />

     

     

    ์ด๋ ‡๊ฒŒ ์ž‘์„ฑํ•ด์ฃผ๋‹ˆ ๋ชฉํ‘œ๋ฅผ ํด๋ฆญํ–ˆ์„ ๋•Œ, ์ฝ˜์†”์— readOnly๊ฐ€ false๋กœ ๋ณ€ํ–ˆ๋‹ค!

     

    ์ด์ œ ๋‹ค์‹œ enter๋ฅผ ๋ˆ„๋ฅด๋ฉด readOnly๋ฅผ true๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.

    ์ด์ „์— ์ž‘์„ฑํ•œ enterKeyEventHandler์™€ ์œ ์‚ฌํ•˜๋‹ค.

     

     

      //readOnly ์ƒํƒœ true๋กœ ๋ณ€๊ฒฝ ํ•จ์ˆ˜
      function enterKeyEventHandler(e){
        if(e.key === 'Enter'){
          readOnlyChange(readOnly = true)
        }
      }

     

     

     

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

     

     

    <Goals goal={goal.items} addGoal={addGoal} deleteGoal={deleteGoal} readOnly={readOnly} 
    readOnlyChange={offReadOnlyMode} enterKeyEventHandler={enterKeyEventHandler} />

     

     

    ๋‹ค์‹œ Goals์—์„œ enterKeyEventHandler๋ฅผ ๋ฐ›์•„์ฃผ๊ณ  (์ด์ „์˜ enterKeyEventHandler ํ•จ์ˆ˜๋Š” GoalForm์— ์žˆ์Œ!)

    onKeyPress๋กœ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์ค€๋‹ค. 

     

     

    <InputBase
      inputProps={{ "aria-label": "naked", readOnly: readOnly, }}
      onClick={readOnlyChange}
      onKeyPress={enterKeyEventHandler}
      type="text"
      id={item.id}
      name={item.id}
      value={item.title}
      multiline={true}
      fullWidth={true}
    />

     

     

     

    ์ด์ œ readOnly๋ฅผ ๋งŒ๋“ค์–ด์คฌ์œผ๋‹ˆ item์„ ์ˆ˜์ •ํ•ด๋ณด์ž.

     

     

    ์šฐ์„  ์ˆ˜์ • ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•œ๋‹ค. state๊ฐ€ ์žˆ๋Š” ๊ณณ์—์„œ ์ž‘์„ฑํ•œ๋‹ค.

     

     //items state ์ˆ˜์ • ํ•จ์ˆ˜
      function editEventHandler(e){
        const thisItems = goal.items; // goal State ์›๋ณธ ์นดํ”ผ
        thisItems.title = e.target.value;
        goalChange({items: thisItems}); //goalChange๋ฅผ ์ด์šฉํ•ด state ๋ณ€๊ฒฝ
      }

     

     

    ์ด edit ํ•จ์ˆ˜๋ฅผ props๋กœ ์ „๋‹ฌํ•ด InputBase์— onChange๋กœ ์—ฐ๊ฒฐํ•œ๋‹ค.

     

     

    <Goals goal={goal.items} addGoal={addGoal} deleteGoal={deleteGoal} 
    readOnly={readOnly} readOnlyChange={offReadOnlyMode} 
    enterKeyEventHandler={enterKeyEventHandler} editEventHandler={editEventHandler} />

     

      let goalItems = props.goal;
      let addGoal = props.addGoal;
      let deleteGoal = props.deleteGoal;
      let readOnly = props.readOnly;
      let readOnlyChange = props.readOnlyChange;
      let enterKeyEventHandler = props.enterKeyEventHandler;
      let editEventHandler = props.editEventHandler;

     

    <InputBase
      inputProps={{ "aria-label": "naked", readOnly: readOnly, }}
      onClick={readOnlyChange}
      onKeyPress={enterKeyEventHandler}
      onChange={editEventHandler}
      type="text"
      id={item.id}
      name={item.id}
      value={item.title}
      multiline={true}
      fullWidth={true}
    />

     

     

     

    ์•„์ด๊ณ  ใ… ใ…  ์ž‘๋™์ด ์•ˆ๋œ๋‹ค....ใ… ใ… ใ… ใ… 

     

    ์šฐ์„ ์€ ๋งˆ๋ฌด๋ฆฌ๋กœ ์ฒดํฌ๋ฐ•์Šค๋ฅผ ํด๋ฆญํ•˜๋ฉด done state๊ฐ€ true๋กœ, ํด๋ฆญ๋˜์—ˆ์„ ๋•Œ, ํด๋ฆญ์„ ํ’€๋ฉด false๋กœ ๋ฐ”๋€Œ๋„๋ก ํ•ด๋ณธ๋‹ค.

     

      //์ฒดํฌ๋ฐ•์Šค ํด๋ฆญ ํ•จ์ˆ˜
      function checkboxEventHandler(e){
        const thisItems = goal.items;
        thisItems.done = !thisItems.done;
        goalChange({items: thisItems})
      }

     

     

    ์ด ํ•จ์ˆ˜๋ฅผ props๋กœ ๋ณด๋‚ด checkbox ์— ์—ฐ๊ฒฐํ•œ๋‹ค.

     

    <Goals goal={goal.items} addGoal={addGoal} deleteGoal={deleteGoal} 
    readOnly={readOnly} readOnlyChange={offReadOnlyMode} 
    enterKeyEventHandler={enterKeyEventHandler} editEventHandler={editEventHandler}
    checkboxEventHandler={checkboxEventHandler} />

     

     

    import React from "react";
    import { Checkbox, IconButton, InputBase, ListItem, ListItemText } from "@mui/material";
    import GoalForm from "./GoalForm";
    import { ListItemSecondaryAction } from "@material-ui/core";
    
    export default function Goals(props) {
      console.log(props);
      let goalItems = props.goal;
      let addGoal = props.addGoal;
      let deleteGoal = props.deleteGoal;
      let readOnly = props.readOnly;
      let readOnlyChange = props.readOnlyChange;
      let enterKeyEventHandler = props.enterKeyEventHandler;
      let editEventHandler = props.editEventHandler;
      let checkboxEventHandler = props.checkboxEventHandler;
    
    
      //๋ชฉํ‘œ ์‚ญ์ œ ์ด๋ฒคํŠธํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜
    
        function deleteEventHandler(e) {
          console.log( 'id : ',  e.target.id)
          deleteGoal(e.target.id, goalItems)
        }
    
        
     
    
      return (
        <>
        <GoalForm addGoal={addGoal} />
    
            {
            goalItems.map((item, idx) => {
             
            return ( <ListItem className="goals-wrap" key={item.id} > { console.log('item: ', item) }
                        <Checkbox checked={item.done} onChange={checkboxEventHandler} />
                        <ListItemText>
                        <InputBase
                            inputProps={{ "aria-label": "naked", readOnly: readOnly, }}
                            onClick={readOnlyChange}
                            onKeyPress={enterKeyEventHandler}
                            onChange={editEventHandler}
                            type="text"
                            id={item.id}
                            name={item.id}
                            value={item.title}
                            multiline={true}
                            fullWidth={true}
                        />
                        </ListItemText>
                        <ListItemSecondaryAction>
                        <IconButton aria-label="Delete Todo" id={item.id} 
                        onClick={deleteEventHandler} sx={{ fontSize: '14px' }}>
                            ์‚ญ์ œ
                        </IconButton>
                    </ListItemSecondaryAction>
                    </ListItem>
                    );
                })
            }
        </>
      );
    }

     

    ์•ˆ๋œ๋‹ค...

     

     

    ์™ ์ง€.. ์‚ญ์ œ ๊ตฌํ˜„ํ–ˆ์„ ๋•Œ์˜ ๋ฌธ์ œ์ฒ˜๋Ÿผ ํด๋ž˜์Šคํ˜•์—์„œ๋Š” this๋ฅผ ์จ์„œ ์ด๋ฒคํŠธ๋ฅผ ์žก์•„๋‚ด๋Š”๋ฐ this๊ฐ€ ๋น ์ ธ๋ฒ„๋ฆฌ๋ฉด์„œ ์–ด๋–ค๊ฒŒ ํด๋ฆญ๋˜์—ˆ๋Š”์ง€ ์ œ๋Œ€๋กœ ์•ˆ์žกํ˜€์„œ ๊ทธ๋Ÿฐ ๊ฒƒ ๊ฐ™๋‹ค.

    (e)๊ฐ€ ์žˆ๋Š”๋ฐ๋„...

     

    ๋‘˜ ๋‹ค ๋น„์Šทํ•œ ๋ฌธ์ œ์ธ ๊ฒƒ ๊ฐ™์œผ๋‹ˆ ๋‚˜์ค‘์— ์ˆ˜์ •ํ•ด์•ผ๊ฒ ๋‹ค ใ… ใ… ใ… ใ… ใ… 

     

     

    ์ด๊ฑฐ ํ•ด๊ฒฐํ•˜๋ฉด ์ž…๋ ฅ ๋ถ€๋ถ„๊ณผ ์ถœ๋ ฅ ๋ถ€๋ถ„ ํ™”๋ฉด์„ ๋”ฐ๋กœ ๋ถ„๋ฆฌ์‹œ์ผœ์•ผ๊ฒ ์Œ!!

     

     

     

     

    728x90

    ๋Œ“๊ธ€

Designed by Tistory.