[React] React 기본 문법

Seojin Kwak·2023년 3월 6일
0

React

생성

npx create-react app . // 현재 디렉토리에 프로젝트 생성

npm start 코드 시행

수정

배포

npm run build

serve: 웹서버. 사용 추천. 노드.
npx serve -s build

=> localhost 말고 네트워크로 배포.

Component

사용자 정의 태그 만들기: 함수 정의 (무조건 대문자)
=> 컴포넌트

// components
function Header() {
  return <header>
    <h1><a href = "/">React</a></h1>
  </header>
}

function Nav() {
  return <nav>
    <ol>
      <li><a href = "/read/1">html</a></li>
      <li><a href = "/read/2">css</a></li>
      <li><a href = "/read/3">js</a></li>
    </ol>
</nav>
}

function Article() {
  return <article>
    <h2>Welcome</h2>
    Hello, WEB
  </article>
}

// main function
function App() {
  return (
    <div className="App">
      <Header />
      <Nav />
      <Article />
    </div>
  );
}

Props

Prop: 속성

function Header(props) {	// 변수명 임의로 props라 설정함
  console.log('props', props, props.title);
  return <header>
    <h1><a href = "/">{props.title}</a></h1>
      // { } 안에 작성 시, 변수 취급
  </header>
}

function App() {
  return (
    <div className="App">
      <Header title = 'REACT'/>
      <Nav />
      <Article />
    </div>
  );
}

콘솔에 다음과 같이 출력됨

>> props {title: 'REACT'} REACT
function Nav(props) {
  const lis = []
  // 반복문
  for(let i = 0; i < props.topics.length; i++){	// 객체 배열 길이: length
    let t = props.topics[i];	// topics 배열을 변수 t에 저장
    lis.push(<li key = {t.id}>	// key라는 prop에는 unique key값 필요. id 값을 key 값으로 저장
      <a href = {"/read/" + t.id}>{t.title}</a>
  	  // 중괄호 사용하여 id값을 주소에 포함
      // title을 내용으로 함
  	</li>)
  }
  return <nav>
    <ol>
      {lis}
    </ol>
  </nav>
}

function App() {
  const topics = [	// 객체 배열 생성
    {id : 1, title: 'html', body: 'html is...'},
    {id : 2, title: 'css', body: 'css is...'},
    {id : 3, title: 'javascript', body: 'javascript is...'}
  ]
  return (
    <div className="App">
      <Header title = 'WEB'/>
      <Nav topics = {topics}/>
      <Article title = 'Welcome' body = 'Hello, WEB'/>
    </div>
  );
}

Event

function Header(props) {
  console.log('props', props, props.title);
  return <header>
    <h1><a href = "/" onClick = {(event) => { // callback 함수. arrow function
      event.preventDefault(); // 기본 동작 방지 => 클릭해도 리로드 X
      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 id = {t.id} href = {"/read/" + t.id} onClick = {(event) => {
        event.preventDefault();
        props.onChangeMode(event.target.id);  
        // event 객체가 가지고 있는 event를 유발시킨 태그 : target
        }}>
      {t.title}</a>
    </li>)
  }
  return <nav>
    <ol>
      {lis}
    </ol>
  </nav>
}

function App() {
  //
  return (
    <div className="App">
      <Header title = 'WEB' onChangeMode = {() => {
        alert('Header');
      }}/>
      <Nav topics = {topics} onChangeMode = {(id) => {
        alert(id);
      }}/>
      <Article title = 'Welcome' body = 'Hello, WEB'/>
    </div>
  );
}

State

prop: 컴포넌트를 사용하는 외부자를 위한 data
state: 컴포넌트를 만드는 내부자를 위한 data

import { useState } from 'react';

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}>
      // t.id는 원래 숫자. 하지만 태그의 속성에 들어가는 순간 문자가 됨.
      <a id = {t.id} href = {"/read/" + t.id} onClick = {(event) => {
        event.preventDefault();
        props.onChangeMode(Number(event.target.id));
        // Number로 변환 안 해주면 문자열 값.
        }}>
      {t.title}</a>
    </li>)
  }
  return <nav>
    <ol>
      {lis}
    </ol>
  </nav>
}

function App() {
  /*
  const _mode = useState('WELCOME');	// 초기값 설정
  const mode = _mode[0];	// 상태의 값을 읽음
  const setMode = _mode[1];	// 상태의 값을 변경할 때 사용하는 함수
  console.log('_mode', _mode);
  */
  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>
  }
  return (
    <div className="App">
      <Header title = 'WEB' onChangeMode = {() => {
        setMode('WELCOME');
      }}/>
      <Nav topics = {topics} onChangeMode = {(id) => {
        setMode('READ');
      }}/>
      {content}
    </div>
  );
}

CRUD

Create

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 태그 사용
      <p><input type = 'text' name = 'title' placeholder = 'title' /></p>
      <p><textarea name = 'body' placeholder = 'body' /></p>
      <p><input type = 'submit' value = 'Create' /></p>
    </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);
    }}/>
  }
  return (
    <div className="App">
      <Header title = 'WEB' onChangeMode = {() => {
        setMode('WELCOME');
      }}/>
      <Nav topics = {topics} onChangeMode = {(_id) => {
        setMode('READ');
        setId(_id);
      }}/>
      {content}
      <a href = '/create' onClick = {(event) => {
        event.preventDefault();
        setMode('CREATE');
      }}>Create</a>
    </div>
  );
}

Update

function Update(props) {
  // useState 사용하여 업데이트
  const [title, setTitle] = useState(props.title);
  const [body, setBody] = useState(props.body);
  return <article>
    <h2>Update</h2>
    <form onSubmit = {(event) => {
      event.preventDefault();
      const title = event.target.title.value;
      const body = event.target.body.value;
      props.onUpdate(title, body);
    }}>
      // onChange 속성 함수로 변경 내용 실시간 반영
      <p><input type = 'text' name = 'title' placeholder = 'title' value = {title} onChange = {(event) => {
        setTitle(event.target.value);
      }}/></p>
      <p><textarea name = 'body' placeholder = 'body' value = {body} onChange = {(event) => {
        setBody(event.target.value);
      }}/></p>
      <p><input type = 'submit' value = 'Update' /></p>
    </form>
  </article>
}

function App() {
  //
  let content = null;
  let contextControl = null;	// READ 모드일 때만 확인 가능한 context
  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>
    contextControl = <li><a href = {'/update/' + id} onClick = {(event) => {
      event.preventDefault();
      setMode('UPDATE');
    }}>Update</a></li>
  } else if (mode === 'CREATE') {
    //
  } else if (mode === 'UPDATE') {
    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 = <Update title = {title} body = {body} onUpdate = {(title, body) => {
      const newTopics = [...topics]
      const updatedTopic = {id: id, title: title, body: body}
      for(let i = 0; i < newTopics.length; i++){
        if(newTopics[i].id === id){
          newTopics[i] = updatedTopic;
          break;
        }
      }
      setTopics(newTopics);
      setMode('READ');
    }}/>
  }
  return (
    //
      <ul>
        <li><a href = '/create' onClick = {(event) => {
          event.preventDefault();
          setMode('CREATE');
        }}>Create</a></li>
        {contextControl}
      </ul>
    </div>
  );
}

Delete

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>
    contextControl = <>
      <li><a href = {'/update/' + id} onClick = {(event) => {
        event.preventDefault();
        setMode('UPDATE');
      }}>Update</a></li>
      <li><input type = 'button' value = 'Delete' onClick = {() => {
        const newTopics = []
        for(let i = 0; i < topics.length; i++){
          // 현재 id에 해당하지 않는 topics의 id들만 newTopics 배열에 push
          if(topics[i].id !== id){
            newTopics.push(topics[i]);
          }
        }
        setTopics(newTopics);
        setMode('WELCOME');
      }} /></li>
    </>
  } 

생활코딩 React 강의 2022 개정판
https://youtu.be/AoMv0SIjZL8

profile
Hello, World!

0개의 댓글