본문 바로가기

블록체인 기반 핀테크 및 응용 SW개발자 양성과정 일기

[76일차] 20210630 React 리액트 push, children

반응형

 

어제 과제 이어서 만드는 input box에 입력하면 입력값 push

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>리액트 시간</title>
    <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
    <link rel="stylesheet" href="./example6.css">
</head>

<body>
    <div id="root">
    </div>
    <script type="text/babel">

        class ComponentForm extends React.Component {
            render() {
                return (
                    <li className="comment-form">
                        <form onSubmit={this.props.onSubmit}>
                            <h4>댓글쓰기 <span>({this.props.length})</span></h4>
                            <span className="ps_box">
                                <input type="text" name="comment_text" placeholder="댓글내용을 입력해주세요." className="int" />
                            </span>
                            <input type="submit" value="등록" className="btn" />
                        </form>
                    </li>
                )
            }
        }

        class ComponentRow extends React.Component {

            render() {
                return (
                    <li>
                        <ul className="comment-row">
                            <li className="comment-id">{this.props.userid}</li>
                            <li className="comment-content">{this.props.content}</li>
                            <li className="comment-date">{this.props.date}</li>
                        </ul>
                    </li>
                )
            }
        }

        class CommentApp extends React.Component {
            constructor(props) {
                super(props)

                this.state = {
                    comments: [
                        { userid: 'asdf', content: '1111', date: '2021-06-30' },
                        { userid: 'asdf', content: '2222', date: '2021-06-30' },
                        { userid: 'asdf', content: '3333', date: '2021-06-30' }
                    ]
                }
            }

            //반복해서 만드는 함수 
            renderRow = () => {
                let { comments } = { ...this.state }
                console.log(comments)
                return (
                    comments.map((v, k) => {
                        return(
                        <ComponentRow
                            key={k} //react가 요구하는 key값! 
                            userid={v.userid}
                            content={v.content}
                            date={v.date}
                        />
                        )
                    })
                )
            }

            onSubmit=(e)=>{
                e.preventDefault()
                //e.target = event 가 발생한 DOM이 무엇이냐 = form element
                console.log(e.target.comment_text.value)
                console.log(e.target.querySelector('.int').value)
                // form 안에 span이 있어서 못찾을까봐 className으로 찾음  !
                let input=e.target.querySelector('.int').value
                let obj = { userid: 'new', content: 'gg', date: '2021-06-30' }
                //react는 push 하면 안됨!! 
                // setState에 위에 추가된 내용을 그려줘야함.. push하면 값을 넣어주지만
                // render를 하지 않음 -> 방법 - 기존 값을 복사해오기 

                // copy해옴 - 불변성의 법칙 - 기존의 값을 그대로 복사해서 추가해라 ! 
                let {comments} = {...this.state}
                console.log(comments)
                comments.push(obj)
                console.log(comments)

                this.setState({comments:comments})
                e.target.reset();
            }

            render() {
                return (
                    <ul className="comment">
                        <ComponentForm 
                            length={this.state.comments.length} 
                            onSubmit={this.onSubmit} 
                        />
                        {this.renderRow()}
                    </ul>
                )
            }
        }

        ReactDOM.render(
            <CommentApp />,
            document.querySelector('#root')
        )
    </script>
</body>

</html>

 

 


 

 

앞으로 공부할 것들 

CRA 란 ? Creat React App 

Node.js환경에서 npm 설치할 수 있다. 셋팅을 자동으로 세팅해주는 것 ! 

 

우리는 Components를 많아야 4개 만들었는데 Facebook은 약 20000개.............

코드 관리위해 라이브러리가 필요 !

React에 필요한 것들 === Babel, Webpack, React, ReactDOM  -> 셋팅을 해주는 좋은 도구들 

Babel, Webpack은 페이스북이 만든건 아니고 React만들 때 가져옴

 

Babel - 구문 짧게 만들어주고 JSX 사용하는 / <>  </> 이것도 Bable에 의해 가능함. html안에서 코드변형할 때 사용 

Webpack - JS build 파일 중 하나 / JS 파일 20000개를 ---함축--->1개로 만들어주는 build 해주는 아이 / 그 외 기능들도 많음 (아직 우리가 안씀) 

React - React 구문 ex) React.Component{} , React.DOM()... 

React-dom - 화면 그려주는 아이 / 결과물보여줄 때 html과 비교하여 다른 부분만 return하는 기능 

 

 

다음 주부터 위의 라이브러리 직접적으로 개발환경 만드는걸 해볼 것 -> 눈으로 직접 어떻게 구동되는지 보기위함 

 

 

Component 

1. class component

옛날에 구현된 코드들은 class ---요즘 추세는 function으로 넘어가는중 --

2. function component 

function이 좋다고 함 하지만 (각 회사 개발 스타일에 따라 다름 ) 예전 좋은 코드들은 class 라서 참고할 때 필요 ! 

=> 둘 다 배울 것. 다음 주부터 함수형으로 배울 것 / 둘 중 어떤걸 쓰더라도 일관성있게 하나만 쓰기 ! 

 

 

리액트 친구 = 리덕스

state 과 관련한 툴, state 불편한 점 : 최상위에서 아래로 내려가기 -> 리덕스 패키지로 조금 더 편하게 작업할 수 잇음 

 

Next.js  === 리액트 

- 좀 더 쉽게 개발할 수 있는 툴

 

React Native

Application 코드 언어로 build 

JS언어를 아이폰 (Swift) , 안드로이드(Kotlin) 언어로 바꾸는 기능

webview 기능 (어플 만들 때 브라우저만 만들고 웹페이지 띄우기 )

장점 : webpage 수정하면 어플 수정하기 쉬움 (어플 업데이트 쉽게 가능) 

 

 


 

 

constructor(props){

    super(props)

    state = { } 

}

요 구문을 위의 사진처럼 짧게 만들 수 있다. (babel 의 기능) 

        class App extends React.Component {
            state={             // <- 요건 React Babel 환경에서만 ! JS는 다 써야함 
                text:'GOOD MORNING'
            }
            render() {
                return (
                    <div>
                        {this.state.text}
                    </div>
                )
            }
        }

        ReactDOM.render(
            <App />,
            document.querySelector('#root')
        )

 

 

 

합성과 상속 

어제의 코드를 Header부분을 만든다고 가정하고! 

 

1. Header Component만들어 넣기 

children을 쓰게되면 Header를 아래처럼 쓸 수 있다.

    <div id="root"></div>
    <script type="text/babel">

        class Header extends React.Component{
            render(){
                return(
                    <ul className="comment">
                        {this.props.children}
                    </ul>
                )
            }
        }

        class App extends React.Component {
            state={
                text:'GOOD MORNING'
            }
            render() {
                return (
                    <Header>
                        내용을 넣을 수 있습니다. 
                    </Header>
                )
            }
        }

        ReactDOM.render(
            <App />,
            document.querySelector('#root')
        )

 

2. logo Component 만들고 넣어보기 

        class Logo extends React.Component {
            render() {  
                return (
                    <li className="comment-form">  
                        <form>
                            <h4>댓글쓰기 <span>(3)</span></h4>
                            <span className="ps_box">
                                <input type="text" placeholder="댓글내용을 입력해주세요." className="int" />
                            </span>
                            <input type="submit" value="등록" className="btn" />
                        </form>
                    </li>
                )
            }
        }

        class Header extends React.Component {
            render() {
                return (
                    <ul className="comment">
                        {this.props.children}
                    </ul>
                )
            }
        }

        class App extends React.Component {
            state = {
                text: 'GOOD MORNING'
            }
            render() {
                return (
                    <Header>
                        <Logo />
                        내용을 넣을 수 있습니다.
                    </Header>
                )
            }
        }

        ReactDOM.render(
            <App />,
            document.querySelector('#root')
        )

 

 

3. Menu /MenuItem Component 만들기  + App  Header Logo 아래에 넣어주기 

        class Logo extends React.Component {
            render() {
                return (
                    <li className="comment-form">
                        <form>
                            <h4>댓글쓰기 <span>(3)</span></h4>
                            <span className="ps_box">
                                <input type="text" placeholder="댓글내용을 입력해주세요." className="int" />
                            </span>
                            <input type="submit" value="등록" className="btn" />
                        </form>
                    </li>
                )
            }
        }

        class Header extends React.Component {
            render() {
                return (
                    <ul className="comment">
                        {this.props.children}
                    </ul>
                )
            }
        }

        class Menu extends React.Component {
            render() {
                return(
                    <>
                        <MenuItem/>
                        <MenuItem/>
                        <MenuItem/>
                        <MenuItem/>
                    </>
                )
            }
        }

        class MenuItem extends React.Component {
            render() {
                return (
                    <li> 
                        <ul className="comment-row">
                            <li className="comment-id">web7722</li>
                            <li className="comment-content">안녕하세요 방가</li>
                            <li className="comment-date">20221-06-28</li>
                        </ul>
                    </li>
                )
            }
        }

        class App extends React.Component {
            state = {
                text: 'GOOD MORNING'
            }
            render() {
                return (
                    <Header>
                        <Logo />
                        <Menu />
                    </Header>
                )
            }
        }

        ReactDOM.render(
            <App />,
            document.querySelector('#root')
        )

 

 


 

 

 

Header - logo, menu, util Component 만들어서 구현해보기 

 

1. Header - children / Logo, Menu, Utill Component 기본 만들기 

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>리액트 시간</title>
    <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
    <link rel="stylesheet" href="./example6.css">
</head>

<body>

    <div id="root"></div>
    <script type="text/babel">

        class Header extends React.Component{
            render(){
               return(
                   <div className="header">
                        {this.props.children}
                    </div>
               )
            }
        }

        class Logo extends React.Component{
            render(){
                return ;
            }
        }

        class Menu extends React.Component{
            render(){
                return ;
            }
        }


        class Utill extends React.Component{
            render(){
                return ;
            }
        }

        class App extends React.Component{
            render(){
                return(
                    <Header>
                        <Logo />
                        <Menu />
                        <Utill />
                    </Header>
                )
            }
        }

        ReactDOM.render(
            <App/>,
            document.querySelector('#root')
        )

    </script>
</body>

</html>

 

 

 

* React는 a tag를 쓰면 안됨 ! React는 SPA (Single Page Application)인데 a를 쓰면 의미가 없어짐 ! 나중에 다른거 쓰는걸 배울 예정 

 

 

2. Logo(h1), Menu(ul,li), Utill(ul,li) 내용 채우기 

        class Logo extends React.Component{
            render(){
                return(
                    <h1>Logo</h1>
                )
            }
        }

        class Menu extends React.Component{
            render(){
                return(
                    <ul>
                        <li>menu1</li>
                        <li>menu2</li>
                        <li>menu3</li>
                        <li>menu4</li>
                    </ul>
                )
            }
        }


        class Utill extends React.Component{
            render(){
                return(
                    <ul>
                        <li>로그인</li>
                        <li>회원가입</li>
                    </ul>
                )
            }
        }

 

 

3. Utill 로그인/회원가입 -----> 로그아웃/ 회원정보 표현하기 (isLogin) 

조건부 렌더링 - App state = isLogin:false 추가 

return 안에는 함수나 많은 내용이 들어가는건 비추 ! 

        class Utill extends React.Component {
            login = () => {
                return (
                    <>
                        <li>로그인</li>
                        <li>회원가입</li>
                    </>
                )
            }

            logout = () => {
                return (
                    <>
                        <li>로그아웃</li>
                        <li>회원정보</li>
                    </>
                )
            }
            render() {
                return (
                    <ul>
                        {this.props.isLogin ? this.logout() : this.login()}
                    </ul>
                )
            }
        }

        class App extends React.Component {
            state = {
                isLogin: false,
            }
            render() {
                return (
                    <Header>
                        <Logo />
                        <Menu />
                        <Utill isLogin={this.state.isLogin} />
                    </Header>
                )
            }
        }

ㄷ.

 

 

새로운 html 생성 + App Component 기본 세팅

 

App이 아닌 Login 에서 상태값을 갖기 ---> App에 전달 

 

 

2. LoginBox Component 에 상태 userid, userpw / return form (input 3)  만들기

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>리액트 시간</title>
    <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
    <link rel="stylesheet" href="./example6.css">
</head>

<body>

    <div id="root"></div>
    <script type="text/babel">


        class LoginBox extends React.Component{
            state={
                userid:'',
                userpw:''
            }

            render(){
                return(
                    <form>
                        <input type="text" />
                        <input type="password"/>
                        <button type="submit" >로그인</button>
                    </form>
                )
            }
        }

        class App extends React.Component{
            state={

            }
            render(){
                return(
                    <LoginBox />
                )
            }
        }

        ReactDOM.render(
            <App/>,
            document.querySelector('#root')
        )


    </script>
</body>

</html>

 

 

3. LoginBox

        class LoginBox extends React.Component {
            state = {
                userid: '',
                userpw: ''
            }

            render() {
                return (
                    <form>
                        <input
                            type="text"
                            placeholder="아이디를 입력해주세요"
                            value={this.state.userid}
                            name="userid"
                        />
                        <input
                            type="password"
                            placeholder="비번을 입력해주세요"
                            value={this.state.userpw}
                            name="userpw"
                        />
                        <button type="submit" >로그인</button>
                    </form>
                )
            }
        }

 

-> 내용은 뜨지만 오류 있다. 

 

 

4. input box에 넣은 값을 onChange로 바꿔주기 (오류 수정)  

        class LoginBox extends React.Component {
            state = {
                userid: '',
                userpw: ''
            }

            handleChange=(e)=>{
                //들어오는 input name 대로 바꾸기 위함 (input이 너무 많을 때)
                this.setState({[e.target.name]:e.target.value})
            }

            render() {
                return (
                    <form>
                        <input
                            type="text"
                            placeholder="아이디를 입력해주세요"
                            value={this.state.userid}
                            name="userid"
                            onChange={this.handleChange}
                        />
                        <input
                            type="password"
                            placeholder="비번을 입력해주세요"
                            value={this.state.userpw}
                            name="userpw"
                            onChange={this.handleChange}
                        />
                        <button type="submit" >로그인</button>
                    </form>
                )
            }
        }

내용이 써진다 

 

 

5. 페이지 이동없이 값이 사라지게 만들기 

        class LoginBox extends React.Component {
            state = {
                userid: '',
                userpw: ''
            }

            handleChange=(e)=>{
                //들어오는 input name 대로 바꾸기 위함 (input이 너무 많을 때)
                this.setState({[e.target.name]:e.target.value})
            }

            handleSubmit=(e)=>{
                e.preventDefault()
                this.setState({
                    userid:'',
                    userpw:'',
                })
            }

            render() {
                return (
                    <form onSubmit={this.handleSubmit}>
                        <input
                            type="text"
                            placeholder="아이디를 입력해주세요"
                            value={this.state.userid}
                            name="userid"
                            onChange={this.handleChange}
                        />
                        <input
                            type="password"
                            placeholder="비번을 입력해주세요"
                            value={this.state.userpw}
                            name="userpw"
                            onChange={this.handleChange}
                        />
                        <button type="submit" >로그인</button>
                    </form>
                )
            }

 

 

 

6. App에 값 전달하기  -> console.log 찍힌거 - > App Component에서 찍혔다는게 중요 ! 

        class LoginBox extends React.Component {
            state = {
                userid: '',
                userpw: ''
            }

            handleChange=(e)=>{
                //들어오는 input name 대로 바꾸기 위함 (input이 너무 많을 때)
                this.setState({[e.target.name]:e.target.value})
            }

            handleSubmit=(e)=>{
                e.preventDefault()
                this.props.onCreate(this.state) // 받음 by App 로그인 버튼 누른 시점에 넘겨주기
                this.setState({   //넘겨주고 reset 
                    userid:'',
                    userpw:'',
                })
            }

            render() {
                return (
                    <form onSubmit={this.handleSubmit}>
                        <input
                            type="text"
                            placeholder="아이디를 입력해주세요"
                            value={this.state.userid}
                            name="userid"
                            onChange={this.handleChange}
                        />
                        <input
                            type="password"
                            placeholder="비번을 입력해주세요"
                            value={this.state.userpw}
                            name="userpw"
                            onChange={this.handleChange}
                        />
                        <button type="submit" >로그인</button>
                    </form>
                )
            }
        }

        class App extends React.Component {

            loginInfo=(data)=>{
                console.log(data)
            }


            render() {
                return (
                    <LoginBox onCreate={this.loginInfo} />
                )
            }
        }

하위 -> 상위로 값을 넘김

 

 

위에서 만든 <Header>와 합치기

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>리액트 시간</title>
    <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
    <link rel="stylesheet" href="./example6.css">
    <style>
        .header{
            display: inline-block;
            float:left
        }
        .header>li{
            display: inline-block;
            float:left   
        }

        .loginbox{
            width:1000px;
            height:200px;
            display: block;
        }

    </style>
</head>

<body>

    <div id="root"></div>
    <script type="text/babel">

        class Header extends React.Component {
            render() {
                return (
                    <div className="header">
                        {this.props.children}
                    </div>
                )
            }
        }

        class Logo extends React.Component {
            render() {
                return (
                    <h1 className="header">Logo</h1>
                )
            }
        }

        class Menu extends React.Component {
            render() {
                return (
                    <ul className="header">
                        <li>menu1</li>
                        <li>menu2</li>
                        <li>menu3</li>
                        <li>menu4</li>
                    </ul>
                )
            }
        }


        class Utill extends React.Component {
            login = () => {
                return (
                    <>
                        <li>로그인</li>
                        <li>회원가입</li>
                    </>
                )
            }

            logout = () => {
                return (
                    <>
                        <li>로그아웃</li>
                        <li>회원정보</li>
                    </>
                )
            }
            render() {
                return (
                    <ul className="header">
                        {this.props.isLogin ? this.logout() : this.login()}
                    </ul>
                )
            }
        }

        class LoginBox extends React.Component {
            state = {
                userid: '',
                userpw: '',
     
            }

            handleChange=(e)=>{
                //들어오는 input name 대로 바꾸기 위함 (input이 너무 많을 때)
                this.setState({[e.target.name]:e.target.value})
            }

            handleSubmit=(e)=>{
                e.preventDefault()
                this.props.onCreate(this.state) // 받음 by App 로그인 버튼 누른 시점에 넘겨주기
                this.setState({   //넘겨주고 reset 
                    userid:'',
                    userpw:'',
                })
            }


            login_form = () =>{
                return (
                    <form onSubmit={this.handleSubmit} >
                        <input
                            type="text"
                            placeholder="아이디를 입력해주세요"
                            value={this.state.userid}
                            name="userid"
                            onChange={this.handleChange}
                        />
                        <input
                            type="password"
                            placeholder="비번을 입력해주세요"
                            value={this.state.userpw}
                            name="userpw"
                            onChange={this.handleChange}
                        />
                        <button type="submit"  >로그인</button>
                    </form>
                )
            }

            logout_btn = () =>{
                return(
                    <>
                        <button type="submit" onClick={this.props.loginFn} >로그아웃</button>
                    </>
                )
            }

            render() {
                return (
                    <div className="loginbox">
                        {this.props.isLogin ? this.logout_btn() : this.login_form() }
                    </div>
                )
            }
        }


        class App extends React.Component {
            state = {
                isLogin: false,
            }

            loginInfo=(data)=>{
                console.log(data)
                if (data.userid =='admin' && data.userpw=='admin'){
                    this.setState({isLogin:true})
                }
            }

            loginFn=()=>{
                this.setState({isLogin:!this.state.isLogin})
            }

            

            render() {
                return (
                    <>
                        <Header>
                            <Logo />
                            <Menu />
                            <Utill isLogin={this.state.isLogin} />
                        </Header>
                        <LoginBox 
                            onCreate={this.loginInfo} 
                            isLogin={this.state.isLogin} 
                            loginFn={this.loginFn}
                        />
                    </>
                )
            }
        }

        ReactDOM.render(
            <App />,
            document.querySelector('#root')
        )

    </script>
</body>

</html>

 

 

 

반응형