context/index.js


import React, { Component, createContext} from 'react'

const context = createContext()

const { Provider , Consumer: SimpleConsumer } = context

class TodoProvider extends Component {

    state = {
        idx: 0,
        todos : [
            { idx: 0 , text:'test', checked : false }
        ]
    }

    actions = {
        insert_todo : (value) => {

            let new_idx = this.state.idx
            new_idx++

            this.setState({
                idx: new_idx,
                todos: [
                    ...this.state.todos,
                    {
                        idx: new_idx,
                        text: value,
                        checked: false
                    }
                ]
            })

        },
        delete_todo: (idx) => {
            this.setState( {
              ...this.state,
              todos: this.state.todos.filter((data) => data.idx !== idx)
          })
        },
        toggle_todo: (idx) => {
            this.setState( {
                ...this.state,
                todos: this.state.todos.map( (data) => {
                    if(data.idx === idx){
                        data.checked = !data.checked
                    }
                    return data
                })
            })
        }
    }


    render() {

        const { state, actions } = this
        const value = {state , actions }
        return (
            <Provider value={value}>
                {this.props.children}
            </Provider>
        )
    }
}

export {
    TodoProvider, SimpleConsumer
}

App.js


import React from 'react';
import { TodoProvider } from './context/index'
import TodoList from './components/TodoList'
import TodoInsert from './components/TodoInsert'
import './App.css';

function App() {
  return (
      <TodoProvider>
        <div className="App">
          <TodoList/>
          <TodoInsert/>
        </div>
      </TodoProvider>
  );
}

export default App;

components/TodoInsert.js


import React, { Fragment, Component } from 'react'
import { SimpleConsumer } from '../context/index'
import styled from 'styled-components'

class Todo extends Component {

    state = {
        input : ''
    }

    handleChange = (e) => {
        this.setState({
            input: e.target.value
        })
    }

    handleSave = (e) => {
        this.props.setValue(this.state.input)
        this.setState({input : ''})
    }

    handleUp = (e) => {
        if(e.keyCode === 13){
            this.handleSave()
        }
    }


    render() {
        return (
            <Fragment>
                <Input type="text" value={this.state.input} 
                onChange={this.handleChange} 
                onKeyDown={this.handleUp}>
                </Input>
                <button onClick={this.handleSave}>저장</button>
            </Fragment>
        )
    }
}

const Input = styled.input`
    margin-left: 20px;
    width: 250px;
    margin-right: 5px;
`


const SendsContainer = () => (
    <SimpleConsumer>
        {
            ({actions})=> (
                <Todo setValue={actions.insert_todo}/>
            )
        }
    </SimpleConsumer>
)

export default SendsContainer

components/TodoList.js


import React from 'react'
import { SimpleConsumer } from '../context/index'
import styled from 'styled-components'

const list = () => {
    return (
        <ul>
            <SimpleConsumer>
                {
                    ({state, actions}) => {
                        return state.todos.map(t =>
                            <Li key={t.idx}>
                                <Span done={t.checked ? true : false} onClick={ (e) =>
                                    actions.toggle_todo(t.idx)
                                }>{t.text}</Span>
                                <Button onClick={ (e) =>
                                    actions.delete_todo(t.idx)
                                }>삭제</Button>
                            </Li>
                        )
                    }

                }
            </SimpleConsumer>
        </ul>
    )
}

const Li = styled.li`
    width: 280px;
    position: relative;
    margin: 3px;
`

const Span = styled.span`
   text-decoration : ${props => props.done ? "line-through" : "none"};
   cursor: pointer;
`

const Button = styled.button`
    position: absolute;
    right:0;
`

export default list

+ Recent posts