대부분의 application이 가지고 있는 4가지 기능

💡 CRUD

  • CREATE : 생성
  • READ : 읽기
  • UPDATE : 수정
  • DELETE : 삭제

💡 Create

  • Create를 클릭하면 mode가 Create로 바뀌고 해당하는 UI가 나타나게 하기

# mode를 Create로 바꾸기


function App() {
  const [mode, setMode] = useState('WELCOME');
  const [id, setId] = useState(null);  // 초기값 없음
  const topics = [
    {id: 1, title: 'HTML', body: 'HTML is ...'},
    {id: 2, title: 'CSS', body: 'CSS is ...'},
    {id: 3, title: 'JavaScript', body: 'JavaScript is ...'},
  ]
  let content = null;
  if (mode === 'WELCOME') {
    content = <Article title="Welcome" body="Hello, WEB"></Article>
  } else if (mode === 'READ') {
    let title, body = null;  // 초기값 없음
    for (let i = 0; i < topics.length; i++) {
      if (topics[i].id === id) {
        title = topics[i].title;
        body = topics[i].body;
      }
    }
    content = <Article title={title} body={body}></Article>
  } else if (mode === 'CREATE') {  // 📍 mode를 Create로 바꾸기
    content = <Create></Create>
  }
  return (
    <div>
      <Header title="WEB" onChangeMode={() => {
        setMode('WELCOME');
      }}></Header>
      <Nav topics={topics} onChangeMode={(_id) => {
        setMode('READ');
        setId(_id);
      }}></Nav>
      {content}
      <a href="/create" onClick={(event) => {
        event.preventDefault();
        setMode('CREATE');  // 📍 mode를 Create로 바꾸기
      }}>Create</a>
    </div>
  );
}

# Create function 만들기

function Create () {
  return (
    <article>
      <h2>Create</h2>
      <form>
        <p><input type="text" name="title" placeholder="title"></input></p>
        <textarea name="body" placeholder='body'></textarea>
        <input type="submit" value="Create"></input>
      </form>
    </article>
  )
}

# Create 컴포넌트 이용자가 버튼 클릭했을 때 후속 작업 인터페이스 제공

function Create (props) {
  return (
    <article>
      <h2>Create</h2>
      <form onSubmit={(event) => {  // 이벤트 함수 안에 
        // form 태그는 submit을 했을 때 페이지가 리로드된다
        event.preventDefault();  // 리로드 되지 않게 
        // name: title, body인 태그의 value 값 가져오기
        const title = event.target.title.value;  // title의 value
        const body = event.target.body.value;  // body의 value
        props.onCreate(title,body);
      }}>
        <p><input type="text" name="title" placeholder="title"></input></p>
        <textarea name="body" placeholder='body'></textarea>
        <input type="submit" value="Create"></input>
	  </form>
    </article>
  )
}
function App() {
  const [mode, setMode] = useState('WELCOME');
  const [id, setId] = useState(null);
  const [nextId, setNextId] = useState(4)  // 다음 원소의 id 값 입력
  const [topics, setTopics] = useState([  // 상태로 승격 시키기
    {id: 1, title: 'HTML', body: 'HTML is ...'},
    {id: 2, title: 'CSS', body: 'CSS is ...'},
    {id: 3, title: 'JavaScript', body: 'JavaScript is ...'},
  ]);
  let content = null;
  if (mode === 'WELCOME') {
    content = <Article title="Welcome" body="Hello, WEB"></Article>
  } else if (mode === 'READ') {
    let title, body = null;
    for (let i = 0; i < topics.length; i++) {
      if (topics[i].id === id) {
        title = topics[i].title;
        body = topics[i].body;
      }
    }
    content = <Article title={title} body={body}></Article>
  } else if (mode === 'CREATE') {
    content = <Create onCreate={(_title, _body) => {  // title, body 값 받기
      // 새로운 원소 만들기 (객체)
      const newTopic = {id: nextId, title: _title, body: _body,}
      topics.push(newTopic); 
      setTopics(topics);     // ❓ 작동 안됨 
    }}></Create>
  }
  return (
    <div>
      <Header title="WEB" onChangeMode={() => {
        setMode('WELCOME');
      }}></Header>
      <Nav topics={topics} onChangeMode={(_id) => {
        setMode('READ');
        setId(_id);
      }}></Nav>
      {content}
      <a href="/create" onClick={(event) => {
        event.preventDefault();
        setMode('CREATE');  // mode를 Create로 바꾸기
      }}>Create</a>
    </div>
  );
}

❓ 작동 안됨 → 해결 방법

const [value, setValue] = useState(PRIMITIVE);
  • 상태를 만들려는 데이터가 원시 데이터(PRIMITIVE) 타입이면, 기존 하던 방법대로
  • string , number , bigint, boolean, undefined, symbol, null
const [value, setValue] = useState(Object);

// 📍 value 복제 
newValue = {...value}  // 배열이면 newValue = [...value] 로 복제
newValue 변경
setValue (newValue)
  • 상태를 만들려는 데이터가 객체(Object) 타입이면, 처리 방법 달라짐
  • object , array

❗️ 수정

function Create (props) {
  return (
    <article>
      <h2>Create</h2>
      <form onSubmit={(event) => {  // 이벤트 함수 안에 
        // form 태그는 submit을 했을 때 페이지가 리로드된다
        event.preventDefault();  // 리로드 되지 않게 
        // name: title, body인 태그의 value 값 가져오기
        const title = event.target.title.value;  // title의 value
        const body = event.target.body.value;  // body의 value
        props.onCreate(title, body);
      }}>
        <p><input type="text" name="title" placeholder="title"></input></p>
        <p><textarea name="body" placeholder='body'></textarea></p>
        <input type="submit" value="Create"></input>
      </form>
    </article>
  )
}
function App() {
  const [mode, setMode] = useState('WELCOME');
  const [id, setId] = useState(null);
  const [nextId, setNextId] = useState(4);  // 다음 원소의 id 값 입력
  const [topics, setTopics] = useState([  // 상태로 승격 시키기
    {id: 1, title: 'HTML', body: 'HTML is ...'},
    {id: 2, title: 'CSS', body: 'CSS is ...'},
    {id: 3, title: 'JavaScript', body: 'JavaScript is ...'},
  ]);
  let content = null;
  if (mode === 'WELCOME') {
    content = <Article title="Welcome" body="Hello, WEB"></Article>
  } else if (mode === 'READ') {
    let title, body = null;
    for (let i = 0; i < topics.length; i++) {
      if (topics[i].id === id) {
        title = topics[i].title;
        body = topics[i].body;
      }
    }
    content = <Article title={title} body={body}></Article>
  } else if (mode === 'CREATE') {
    content = <Create onCreate={(_title, _body) => {  // title, body 값 받기
      // 새로운 원소 만들기 (객체)
      const newTopic = {id: nextId, title: _title, body: _body,}
      const newTopics = [...topics]  // 📍 배열 복제
      newTopics.push(newTopic);      // 📍 복제본에 push
      setTopics(newTopics);          // 📍 topics 와 newTopics를 비교해서 다르면 컴포넌트 렌더링
    }}></Create>
  }
  return (
    <div>
      <Header title="WEB" onChangeMode={() => {
        setMode('WELCOME');
      }}></Header>
      <Nav topics={topics} onChangeMode={(_id) => {
        setMode('READ');
        setId(_id);
      }}></Nav>
      {content}
      <a href="/create" onClick={(event) => {
        event.preventDefault();
        setMode('CREATE');  // mode를 CREATE로 바꾸기
      }}>Create</a>
    </div>
  );
}

📌 원리 Recheck

// 📍 원시 데이터 타입
const [value, setValue] = useState(1);   
setValue(2);  // 새로운 값
// 오리지널 데이터는 1, 새로운 데이터는 2 이기 때문에 새로 렌더링됨

 // 📍 배열
const [value, setValue] = useState([1]); 
value.push(2);    // 오리지널 데이터를 변경
setValue(value);  // 오리지널 데이터를 입력
// 오리지널 데이터와 새로운 데이터가 같은 데이터인 경우 컴포넌트를 새로 랜더링 하지 않음

→
newValue = [...value]  // 오리지널 데이터 복제
newValue.push(2);      // 복제한 데이터를 변경
setValue(newValue);    // 변경한 데이터를 set

# Create 버튼 눌러 등록할 때 상세 내용 보이게

function App() {
  const [mode, setMode] = useState('WELCOME');
  const [id, setId] = useState(null);
  const [nextId, setNextId] = useState(4); 
  const [topics, setTopics] = useState([ 
    {id: 1, title: 'HTML', body: 'HTML is ...'},
    {id: 2, title: 'CSS', body: 'CSS is ...'},
    {id: 3, title: 'JavaScript', body: 'JavaScript is ...'},
  ]);
  let content = null;
  if (mode === 'WELCOME') {
    content = <Article title="Welcome" body="Hello, WEB"></Article>
  } else if (mode === 'READ') {
    let title, body = null;
    for (let i = 0; i < topics.length; i++) {
      if (topics[i].id === id) {
        title = topics[i].title;
        body = topics[i].body;
      }
    }
    content = <Article title={title} body={body}></Article>
  } else if (mode === 'CREATE') {
    content = <Create onCreate={(_title, _body) => {
      const newTopic = {id: nextId, title: _title, body: _body,}
      const newTopics = [...topics] 
      newTopics.push(newTopic); 
      setTopics(newTopics);
      setMode('READ');  // 상세 페이지 열리게
      setId(nextId);    // 추가 내용 입력 시 id 값
      setNextId(nextId + 1);
    }}></Create>
  }
  return (
    <div>
      <Header title="WEB" onChangeMode={() => {
        setMode('WELCOME');
      }}></Header>
      <Nav topics={topics} onChangeMode={(_id) => {
        setMode('READ');
        setId(_id);
      }}></Nav>
      {content}
      <a href="/create" onClick={(event) => {
        event.preventDefault();
        setMode('CREATE'); 
      }}>Create</a>
    </div>
  );
}

# 완성

import './App.css';
import {useState} from 'react';

function Header (props) {
  console.log('props', props, props.title);
  return (
  <header>
    <h1><a href="/" onClick={(event) => {
      event.preventDefault();
      props.onChangeMode();
    }}>{props.title}</a></h1>
  </header>
  )
}
function Nav (props) {
  const lis = [];
  for (let i = 0; i < props.topics.length; i++) {
    let t = props.topics[i];
    lis.push(
      <li key={t.id}>  
        <a href={'/read/'+t.id} onClick={(event) => {
          event.preventDefault();
          props.onChangeMode(Number(t.id));
        }}>{t.title}</a>
      </li>
    )
  }
  return (
    <nav>
      <ol>
        {lis}
      </ol>
    </nav>
  )
}
function Article (props) {
  return (
    <article>
      <h2>{props.title}</h2>
      {props.body}
    </article>
  )
}
function Create (props) {
  return (
    <article>
      <h2>Create</h2>
      <form onSubmit={(event) => {  
        event.preventDefault();  
        const title = event.target.title.value; 
        const body = event.target.body.value;  
        props.onCreate(title, body);
      }}>
        <p><input type="text" name="title" placeholder="title"></input></p>
        <p><textarea name="body" placeholder='body'></textarea></p>
        <input type="submit" value="Create"></input>
      </form>
    </article>
  )
}
function App() {
  const [mode, setMode] = useState('WELCOME');
  const [id, setId] = useState(null);
  const [nextId, setNextId] = useState(4); 
  const [topics, setTopics] = useState([ 
    {id: 1, title: 'HTML', body: 'HTML is ...'},
    {id: 2, title: 'CSS', body: 'CSS is ...'},
    {id: 3, title: 'JavaScript', body: 'JavaScript is ...'},
  ]);
  let content = null;
  if (mode === 'WELCOME') {
    content = <Article title="Welcome" body="Hello, WEB"></Article>
  } else if (mode === 'READ') {
    let title, body = null;
    for (let i = 0; i < topics.length; i++) {
      if (topics[i].id === id) {
        title = topics[i].title;
        body = topics[i].body;
      }
    }
    content = <Article title={title} body={body}></Article>
  } else if (mode === 'CREATE') {
    content = <Create onCreate={(_title, _body) => {
      const newTopic = {id: nextId, title: _title, body: _body,}
      const newTopics = [...topics] 
      newTopics.push(newTopic); 
      setTopics(newTopics);
      setMode('READ');
      setId(nextId);  
      setNextId(nextId + 1);
    }}></Create>
  }
  return (
    <div>
      <Header title="WEB" onChangeMode={() => {
        setMode('WELCOME');
      }}></Header>
      <Nav topics={topics} onChangeMode={(_id) => {
        setMode('READ');
        setId(_id);
      }}></Nav>
      {content}
      <a href="/create" onClick={(event) => {
        event.preventDefault();
        setMode('CREATE'); 
      }}>Create</a>
    </div>
  );
}

export default App;

✨ 끝 !

✦ 출처 : 생활코딩 [React 2022년 개정판]

profile
✧ 중요한건 꺾이지 않는 마음 🔥 ᕙ(•ө•)ᕤ 🔥

0개의 댓글

Powered by GraphCDN, the GraphQL CDN