본문 바로가기

프로그램 강좌

[react.js]게시판 만들기2: 읽고 쓰기

목록, 읽기, 쓰기 모두 axios를 통해 읽을 예정이다. 간편한 예제를 위해 css는 모두 styled-components 를 사용했다. 방법이 헷갈리는 분들은 맨아래 소개 되어 있는 이전 챕터를 활용하면 될것 같다.


/frontend/src/routes/List.js

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
import styled from 'styled-components';

class List extends Component {
  state = {
    boards: [],
  };

  handleChange = (e) => {
    const { name, value } = e.target;
    this.setState({
      [name]: value,
    });
  };
  //로딩 데이터
  loadingData = async () => {
    try {
      const response = await axios.get('http://localhost:4000/board');
      this.setState({
        // boards: 'test'
        boards: response.data,
      });
    } catch (e) {
      console.log(e);
    }
  };
  componentDidMount() {
    const { loadingData } = this;
    loadingData();
  }

  render() {
    const { boards } = this.state;
    const { handleChange } = this;
    return (
      <Wrap>
        <h2>List</h2>
        <div>
          {boards && (
            <textarea
              name="getBoards2"
              onChange={handleChange}
              rows={7}
              value={JSON.stringify(boards, null, 2)}
            />
          )}
        </div>
        {/* {console.log(boards)} */}
        {/* {boards[0].id} */}
        {boards.map((item) => {
          return (
            <ListItem key={item.id}>
              <Link to={`/read/${item.id}`}>
                <h3>{item.title}</h3>
                <p>{item.content}</p>
              </Link>
            </ListItem>
          );
        })}

        <Button>
          {/* <button onClick={handleClick}>get Request</button> */}
          <Link to={`/write`}>글쓰기</Link>
        </Button>
      </Wrap>
    );
  }
}

//styling
const Wrap = styled.div`
  padding: 20px;
`;

const ListItem = styled.div`
  width: 100%;
  margin-top: 10px;
  padding: 20px;
  border-top: 1px solid #eee;
  a {
    text-decoration: none;
    h3 {
      margin: 0;
      padding: 0;
      color: #212121;
    }
    p {
      margin: 0;
      padding: 10px 0 0 0;
      color: #787878;
    }
    &:hover {
      h3 {
        color: #0066ff;
      }
    }
  }
`;
const Button = styled.div`
  border-top: 1px solid #eee;
  padding: 20px;
  a {
    float: right;
    padding: 10px 20px;
    border-radius: 5px;
    text-decoration: none;
    background: #212121;
    color: #fff;
  }
`;

export default List;



 

/frontend/src/routes/Read.js

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
import styled from 'styled-components';

class Read extends Component {
  state = {
    id: '',
    board: [],
  };

  //로딩 데이터
  loadingData = async () => {
    //test JSON: 이 주소로 넣으면 오류 없음
    //https://jsonplaceholder.typicode.com/todos/1
    try {
      // const id = 0; //test id
      const { id } = this.props.match.params;
      console.log(id);
      const response = await axios.get(`http://localhost:4000/board/${id}`);
      this.setState({
        // boards: 'test'
        board: response.data,
      });
      console.log(response.data);
    } catch (e) {
      console.log(e);
    }
  };
  componentDidMount() {
    const { loadingData } = this;
    loadingData();
  }
  render() {
    const { board } = this.state;
    return (
      <Wrap>
        <h2>{board.title}</h2>
        <p>{board.content}</p>
        <Button>
          <Link to="/">목록</Link>
          <a
            href="#"
            onClick={() => {
              alert('삭제');
            }}
          >
            삭제
          </a>
          <a
            href="#"
            onClick={() => {
              alert('수정');
            }}
          >
            수정
          </a>
        </Button>
      </Wrap>
    );
  }
}

//styling
const Wrap = styled.div`
  padding: 20px;
  h2 {
    padding-bottom: 20px;
    border-bottom: 1px solid #ccc;
  }
  p {
    min-height: 200px;
  }
`;
const Button = styled.div`
  border-top: 1px solid #eee;
  padding: 20px;
  a {
    float: right;
    padding: 10px 20px;
    border-radius: 5px;
    text-decoration: none;
    background: #f2f2f2;
    border: 1px solid #ddd;
    color: #424242;
    font-size: 16px;
  }
  a + a {
    margin-right: 5px;
  }
`;

export default Read;

 

/frontend/src/routes/Write.js

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
import styled from 'styled-components';

class Write extends Component {
  state = {
    title: '',
    content: '',
  };
  postBoard = async () => {
    const { title, content } = this.state;
    const post = await axios.post('http://localhost:4000/board', {
      title,
      content,
    });
    // alert('전송');

    this.setState({
      title: '',
      content: '',
    });
    console.log(post);
  };
  handleChange = (e) => {
    const { name, value } = e.target;
    this.setState({
      [name]: value,
    });
  };
  render() {
    return (
      <Wrap>
        <h2>Write</h2>
        <p>
          <input
            type="text"
            name="title"
            onChange={this.handleChange}
            value={this.state.title}
          />
        </p>
        <p>
          <textarea
            type="text"
            name="content"
            onChange={this.handleChange}
            value={this.state.content}
          />
        </p>
        <Button>
          <button onClick={this.postBoard}>전송하기 </button>
          <Link to="/">목록</Link>
        </Button>
        <div>{JSON.stringify(this.state)}</div>
      </Wrap>
    );
  }
}

//styling
const Wrap = styled.div`
  padding: 20px;
  input {
    width: 100%;
    height: 20px;
    border: 1px solid #ccc;
  }
  textarea {
    width: 100%;
    height: 100px;
    border: 1px solid #ccc;
  }
`;
const Button = styled.div`
  border-top: 1px solid #eee;
  padding: 20px;
  button {
    float: right;
    padding: 10px 20px;
    border-radius: 5px;
    text-decoration: none;
    background: #212121;
    color: #fff;
    font-size: 16px;
  }
  a {
    float: right;
    padding: 10px 20px;
    border-radius: 5px;
    text-decoration: none;
    background: #f2f2f2;
    border: 1px solid #ddd;
    color: #424242;
    font-size: 16px;
  }
  & > button + a {
    margin-right: 5px;
  }
`;

export default Write;

 

기본적으로 페이지들이 생성됐다면 중앙(App.js)에서 관리해주자

/frontend/src/App.js

import React, { Component } from 'react';
import { Route } from 'react-router-dom';
import List from './routes/List';
import Read from './routes/Read';
import Write from './routes/Write';

class App extends Component {
  render() {
    return (
      <div>
        {/* <div className="lnk">
          <ul>
            <li>
              <Link to="/">List</Link>
            </li>
            <li>
              <Link to="/read">Read</Link>
            </li>
            <li>
              <Link to="/write">Write</Link>
            </li>
          </ul>
        </div> */}
        <div className="route">
          <Route exact path="/" component={List} />
          <Route path="/read/:id?" component={Read} />
          <Route path="/write" component={Write} />
        </div>
      </div>
    );
  }
}

export default App;

이제 읽고 쓸 수 있게 됐다.


2020/04/16 - [프로그램 강좌] - [react.js]게시판 만들기1

2020/01/18 - [프로그램 강좌] - [express]게시판만들기 #1

2020/01/20 - [프로그램 강좌] - [express]게시판 만들기 #2

2020/01/18 - [프로그램 강좌] - [express]게시판 만들기 #3

2020/01/29 - [프로그램 강좌] - [express]게시판 만들기 #4






728x90