고래씌

[React] 2-1. 게시판 만들기(제목변경, 목록, 게시글 삭제) 본문

React/node.js

[React] 2-1. 게시판 만들기(제목변경, 목록, 게시글 삭제)

고래씌 2024. 1. 15. 14:44

1. 게시판 만들기(변수)

/* eslint-disable */

import './App.css';

function App() {
  return (
    <div className="App">
      {/* jsx문법 내부에서의 주석
        JSX문법)
        js 문법 내부에 html코드를 작성할 수 있는 문법을 jsx문법이라고 함.
        리액트에서 UI를 구성할 때 보편적으로 사용되는 방법으로 복잡한 코드를 할 필요없이,
        동적으로 추가되는 dom요소를 단순 코드선언으로 생성할 수 있게 도와준다.
      */}
      <div className="header">
        <h3 style={ { fontWeight : "bolder" } }>Whale CLASS</h3>
      </div>
      <div className='nav'>
        <button>게시판</button>
        <button>등록</button>
      </div>
      <div className='outer'>
        <br />
        <h2>일반게시판</h2>
        <table className='list-table'>
          <thead>
            {/* 번호, 제목, 작성자, 작성일, 삭제에 각각
                크기 10%, 40%, 20%, 10% 인라인으로 스타일 부여해주기 */}
            <tr>
              <th style={ {width: "10%"} }>번호</th>
              <th style={ {width: "40%"} }>제목</th>
              <th style={ {width: "20%"} }>작성자</th>
              <th style={ {width: "20%"} }>작성일</th>
              <th style={ {width: "10%"} }>삭제</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>1</td>
              <td>제목1</td>
              <td>마스터</td>
              <td>2023/01/15</td>
              <td><button>삭제</button></td>
            </tr>
            <tr>
              <td>2</td>
              <td>제목2</td>
              <td>마스터</td>
              <td>2023/01/15</td>
              <td><button>삭제</button></td>
            </tr>
            <tr>
              <td>3</td>
              <td>제목3</td>
              <td>마스터</td>
              <td>2023/01/15</td>
              <td><button>삭제</button></td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
  );
}

export default App;

 

 

▶ 변수를 쓰고자할 때

 

=> {} 로 묶어서변수명을 사용해주면 된다.

 

결과

 

 


2. 제목변경(react 방식 event 부여)

 

1) useState

 

 비구조화할당문법 : 배열이나 객체에 들어가 있는 값을 "쉽게" 변수로 할당하는 문법

    let arr = [1,2];
    let a = arr[0];
    let b = arr[1];

    let [a,b] = arr;

    => 변수명을 단축해서 사용할 수 있는 단축구문임



=> useState()함수의 반환값은 길이 2짜리 배열[]이며, 배열비구조화할당문법을 통해 쉽게 배열에 있는 값을 변수로 할당한 것.
=> 반환된 배열의 0번 인덱스에 있는 값을 제목2 변수에, 1번 인덱스에 있는 값을 제목변경함수에 각각 할당한 것.

 

 

=>제목 2로 바꾸고 다시 출력해보면 D CLASS가 아닌 E CLASS가 출력되는 것을 볼수 있다.

 

결과

 

 

 

2) onClick

 

=> 이렇게 쓰면 콘솔창에 버튼을 누르기도 전에 "1"이 이미 실행된 것을 확인할 수 있다. 버튼을 클릭해도 콘솔창에는 이후 반응이 없다.

 

 

▶ onClick={함수}
 주의점 : 무조건 함수자료형값만 넣어줘야함. 함수호출한 결과값 넣어주면 의미가 없다.

 

 

=> 이런식으로 선언을 해주어야 한다!

 

 

▶ 제목변경해보기

=> 제목변경테스트를 클릭하면 제목이 변경된다.

 

=> 단순 대입연산자를 활용하는 경우 state값의 변경점을 reactDom이 알지못함

=> useState의 두번째 매개변수로 전달받은 함수를 통해 변경시 화면이 재랜더링된다.

 

 

 

3. 목록(배열)

▶ Array 내부의 map함수 사용 예제

 

① 배열 변수 선언

    let [게시글배열, 게시글배열변경함수] = useState([{ 글번호: 1, 글제목: '초기게시글 1', 글내용: '다이어트3주차 힘드네요', 작성자: 'admin', 작성일: '2023/12/27'},
                                                  { 글번호: 2, 글제목: '다이어터 식단표 공유', 글내용: '아침 : 삼각김밥, 점심 : 김밥반줄, 저녁 : 삼각김밥', 작성자: 'admin', 작성일: '2023/12/27'},
                                                  { 글번호: 3, 글제목: '다이어트끝나면(1)', 글내용: '편백찜 먹고싶다', 작성자: 'admin', 작성일: '2023/12/27' },
                                                  { 글번호: 4, 글제목: '다이어트끝나면(2)', 글내용: '스키야끼 먹고싶다', 작성자: 'admin', 작성일: '2023/12/27'},
                                                  { 글번호: 5, 글제목: '다이어트끝나면(3)', 글내용: '타코 먹고싶다', 작성자: 'admin', 작성일: '2023/12/27' },
                                                  { 글번호: 6, 글제목: '대충만든 제목', 글내용: '대충만든 글내용', 작성자: 'admin', 작성일: '2023/12/27' },
                                                  { 글번호: 7, 글제목: '다이어트끝나면(4)', 글내용: '치킨 피자 먹고싶다', 작성자: 'admin', 작성일: '2023/12/27' },
                                                  { 글번호: 8, 글제목: '다이어트끝나면(5)', 글내용: '초밥 먹고싶다', 작성자: 'admin', 작성일: '2023/12/27' },
                                                  { 글번호: 9, 글제목: '다이어트끝나면(6)', 글내용: '햄버거 먹고싶다', 작성자: 'admin', 작성일: '2023/12/27' },
                                                  { 글번호: 10, 글제목: '오늘은 무슨날?', 글내용: '치팅데이', 작성자: 'admin', 작성일: '2023/12/29' },
  ]);

 

 

② 배열 반복문

          <tbody>
            {/*
              Array내부의 map함수 사용 예제
              [1,2,3].map(function () {return 1}) ==> [1,1,1]
            */

              게시글배열.map(function(게시글, 인덱스) {
                return (
                  <tr key={인덱스}>
                    <td>{게시글.글번호}</td>
                    <td>{게시글.글제목}</td>
                    <td>{게시글.작성자}</td>
                    <td>{게시글.작성일}</td>
                    <td><button>삭제</button></td>
                  </tr> 
                  )
              })
            }

          </tbody>

 

결과

 

 

- 배열함수선언을 따로 js파일에 넣고 사용하고자한다면...

 

=> export default data; 로 내보내기.

    내보내기 하고 싶은 변수/함수 앞에 export default 구문 추가
    단, default옵션은 파일당 한번만 사용가능

 

- App.js파일에 import추가

 

=> default옵션으로 export한 경우 변수명을 다르게 가져올 수 있음

 

 

▶ 기본 export문

export {변수, 함수명, 변수, ...}

 

 

- 여러 변수를 동시에 내보내기 하고싶을 때

data.js

 

App.js

 

 

 

 

4. 삭제 기능 만들기

▶ 게시글 삭제 기능
1. 삭제하고자하는 게시글을 특정할 수 있어야한다.
2. 게시글배열에서 삭제하고자하는 게시글을 없애준다.
3. 내가 선택한 게시글이 제거된 게시글배열로 화면이 랜더링 되어야한다.

 

 

 

방법 ) 배열에서 삭제를 담당하는 메소드 Array.splice(인덱스위치, 삭제할숫자)

 

 

 

 

=> 1번 글번호를 삭제 버튼을 클릭했을 때 console에서는 삭제된 것을 확인할 수 있지만, 화면상에는 변화가 없다!

 

게시글배열변경함수(게시글배열); 

 

=> 값이 제거된 배열을 넣어줬음에도 랜더링이 이루어지지 않는다.
=> 주소값 자체는 변하지않아서 랜더링이 이루어지지 않음.

=> 랜더링이 이루어주게 하기 위해서는 전개연산자를 사용해야한다.

 

 

 전개연산자

- ...전개연산자 [a,b,c] → a,b,c     // ...{key : value, key: value} → key : value, key: value
- 깊은 복사를 사용하는 것이 전개연산자이다!

- Array.from(게시글배열), 게시글배열.slice(), concat함수 등...

게시글배열변경함수(new Array([...게시글배열]));

 

 

/* eslint-disable */

import './App.css';

import {useState} from 'react';

import 초기게시글 from './data'; // default옵션으로 export한 경우 변수명을 다르게 가져올 수 있음

import {a,b,c} from './data';

function App() {

  let 제목 = "Whale D CLASS";

  // state 문법
  let [제목2, 제목변경함수] = useState('Whale E CLASS');  
  // let [title,setTitle] => set를 붙여서 쓰는게 관례
  // useState => 반환되는 값이 길이 2짜리 변수임 ['Whale E CLASS', function]


    let [게시글배열, 게시글배열변경함수] = useState(초기게시글);

  function 제목2변경() {
    제목변경함수("Whale C CLASS");  // useState의 두번째 매개변수로 전달받은 함수를 통해 변경시 화면이 재랜더링된다.
  }

  const 게시글삭제 = (삭제할글번호) => {
    // 1) 배열에서 삭제를 담당하는 메소드 Array.splice(인덱스위치, 삭제할숫자)
    for(let i = 0; i<게시글배열.length; i++){
      if(게시글배열[i].글번호 == 삭제할글번호) {
        게시글배열.splice(i, 1);
        break;
      }
    }
    
    // ...전개연산자 [a,b,c] → a,b,c     // ...{key : value, key: value} → key : value, key: value
    console.log(게시글배열); 
    게시글배열변경함수(new Array([...게시글배열]));

  }

  return (
    <div className="App">
      <div className="header">
        <h3 style={ { fontWeight : "bolder" } }>{제목2}</h3>
      </div>
      <div className='nav'>
        {/* 
          react방식 event부여
          onClick={함수}
          * 주의점 : 무조건 함수자료형값만 넣어줘야함. 함수호출한 결과값 넣어주면 의미가 없다.
        */}
        <button onClick={제목2변경}>제목변경테스트</button>
        <button>게시판</button>
        <button>등록</button>
      </div>
      <div className='outer'>
        <br />
        <h2>일반게시판</h2>
        <table className='list-table'>
          <thead>
            {/* 번호, 제목, 작성자, 작성일, 삭제에 각각
                크기 10%, 40%, 20%, 10% 인라인으로 스타일 부여해주기 */}
            <tr>
              <th style={ {width: "10%"} }>번호</th>
              <th style={ {width: "40%"} }>제목</th>
              <th style={ {width: "20%"} }>작성자</th>
              <th style={ {width: "20%"} }>작성일</th>
              <th style={ {width: "10%"} }>삭제</th>
            </tr>
          </thead>
          <tbody>
            {/*
              Array내부의 map함수 사용 예제
              [1,2,3].map(function () {return 1}) ==> [1,1,1]
            */

              게시글배열.map(function(게시글, 인덱스) {
                return (
                  <tr key={인덱스}>
                    <td>{게시글.글번호}</td>
                    <td>{게시글.글제목}</td>
                    <td>{게시글.작성자}</td>
                    <td>{게시글.작성일}</td>
                    <td><button onClick={() => {게시글삭제(게시글.글번호)}}>삭제</button></td>
                  </tr> 
                  )
              })
            }

          </tbody>
        </table>
      </div>
    </div>
  );
}

export default App;

 

 

 

방법 ②) 게시글배열에서 글번호와 일치하지 않는 게시글만 필터링하기. (filter함수 이용)

  const 게시글삭제 = (삭제할글번호) => {
    // 2) 게시글배열에서 글번호와 일치하지 않는 게시글만 필터링하기. (filter함수 이용)

    let 필터링배열 = 게시글배열.filter((게시글) => 게시글.글번호 !== 삭제할글번호)
    // let 필터링배열 = 게시글배열.filter(function(게시글) {
    //   return 게시글.글번호 !== 삭제할글번호
    // })

    게시글배열변경함수(필터링배열);
  }

 

function App() {

  const 게시글삭제 = (삭제할글번호) => {

    // 2) 게시글배열에서 글번호와 일치하지 않는 게시글만 필터링하기. (filter함수 이용)
    let 필터링배열 = 게시글배열.filter((게시글) => 게시글.글번호 !== 삭제할글번호)
    게시글배열변경함수(필터링배열);
  }


  return (
    <div className="App">

      <div className="header">
        <h3 style={ { fontWeight : "bolder" } }>{제목2}</h3>
      </div>
      <div className='nav'>

        <button onClick={제목2변경}>제목변경테스트</button>
        <button>게시판</button>
        <button>등록</button>
      </div>
      <div className='outer'>
        <br />
        <h2>일반게시판</h2>
        <table className='list-table'>
          <thead>
            <tr>
              <th style={ {width: "10%"} }>번호</th>
              <th style={ {width: "40%"} }>제목</th>
              <th style={ {width: "20%"} }>작성자</th>
              <th style={ {width: "20%"} }>작성일</th>
              <th style={ {width: "10%"} }>삭제</th>
            </tr>
          </thead>
          <tbody>
            {/*
              Array내부의 map함수 사용 예제
              [1,2,3].map(function () {return 1}) ==> [1,1,1]
            */

              게시글배열.map(function(게시글, 인덱스) {
                return (
                  <tr key={인덱스}>
                    <td>{게시글.글번호}</td>
                    <td>{게시글.글제목}</td>
                    <td>{게시글.작성자}</td>
                    <td>{게시글.작성일}</td>
                    <td><button onClick={() => {게시글삭제(게시글.글번호)}}>삭제</button></td>
                  </tr> 
                  )
              })
            }

          </tbody>
        </table>