React Redux : 공식 사이트 "Basic Tutorial"의 작례를 후크로 다시 작성

React 16.8부터 함수 컴포넌트에 React 기능 추가후크(hook)가 도입되었습니다. 다리를 맞추고 React Redux 7.1.0에 갖추어진 것이 Redux에 연결한다후크입니다. React Redux 공식 「Basic Tutorial」의 작례 「Todo App with Redux」는, 불행히도 React 16.4.2로 만들어져, 어느 훅도 사용되고 있지 않습니다. 그래서 후크 대응으로 다시 써 보자는 것이 본고의 제목입니다.

>> Todo App with Redux

클래스 구성 요소를 함수 구성 요소로 다시 작성



첫째, 모듈src/components/AddTodo.js은 컴포넌트에 상태( state )를 갖게 하기 때문에 클래스에 정의되어 있습니다. React 훅 useState()을 사용하여 함수 구성 요소로 수정합시다 ( "React Hooks : 클래스의 구성 요소를 useState ()로 함수로 다시 작성"참조). 함수 컴포넌트 중 this 참조가 사라집니다.

src/components/AddTodo.js
// import React from 'react';
import React, { useState } from 'react';

// class AddTodo extends React.Component {
const AddTodo = ({ addTodo }) => {
    /* constructor(props) {
        super(props);
        this.state = { input: '' };
    } */
    const [input, setInput] = useState('');

    // updateInput = input => {
    const updateInput = input => {
        // this.setState({ input });
        setInput(input);
    };

    // handleAddTodo = () => {
    const handleAddTodo = () => {
        // this.props.addTodo(this.state.input);
        addTodo(input);
        // this.setState({ input: '' });
        setInput('');
    };

    // render() {
    return (
        <div>
            <input
                // onChange={e => this.updateInput(e.target.value)}
                onChange={e => updateInput(e.target.value)}
                // value={this.state.input}
                value={input}
            />
            {/* <button className='add-todo' onClick={this.handleAddTodo}> */}
            <button className='add-todo' onClick={handleAddTodo}>
                Add Todo
            </button>
        </div>
    );
    // }
};

useDispatch() 사용



그런 다음 React Redux 후크를 사용합니다. connect() 함수의 두 번째 인수에 주어 액션을 발행하는 dispatch()에 연결하는 후크가 useDispatch()입니다. 액션 크리에이터( addTodo )는 후크에서 반환된 함수( dispatch() )로 호출됩니다.

src/components/AddTodo.js
// import { connect } from 'react-redux';
import { useDispatch } from 'react-redux';

// const AddTodo = ({ addTodo }) => {
const AddTodo = () => {

    const dispatch = useDispatch();

    const handleAddTodo = () => {
        // addTodo(input);
        dispatch(addTodo(input));
    };

};

/* export default connect(
    null,
    { addTodo }
)(AddTodo); */
export default AddTodo;

이제 모듈 src/components/AddTodo.js이 순수한 함수 구성 요소가되었습니다. src/components/Todo.js 또한 useDispatch()connect() 랩을 제거할 수 있습니다.

src/components/Todo.js
// import { connect } from 'react-redux';
import { useDispatch } from 'react-redux';
import cx from 'classnames';
import { toggleTodo } from '../redux/actions';

// const Todo = ({ todo, toggleTodo }) => (
const Todo = ({ todo }) => {
    const dispatch = useDispatch();
    return (
        // <li className='todo-item' onClick={() => toggleTodo(todo.id)}>
        <li className='todo-item' onClick={() => dispatch(toggleTodo(todo.id))}>

        </li>
    );
}

/* export default connect(
    null,
    { toggleTodo }
)(Todo); */
export default Todo;

useSelector() 사용


connect()의 첫 번째 인수 (mapStateToProps)가 담당하는 Store에서 상태 (state)를 검색하는 후크는 useSelector()입니다. 전달하는 함수는 인수( state )의 상태에서 처리된 값을 반환합니다. 모듈src/components/TodoList.js은 다음과 같이 다시 작성해야 합니다.

src/components/TodoList.js
// import { connect } from 'react-redux';
import { useSelector } from 'react-redux';

// const TodoList = ({ todos }) => (
const TodoList = () => {
    const todos = useSelector(state => {
        const visibilityFilter = state.visibilityFilter;
        const todos = getTodosByVisibilityFilter(state, visibilityFilter);
        return todos;
    });

}

/* const mapStateToProps = state => {
    const { visibilityFilter } = state;
    const todos = getTodosByVisibilityFilter(state, visibilityFilter);
    return { todos };
};
export default connect(mapStateToProps)(TodoList); */
export default TodoList;

나머지 모듈src/components/VisibilityFilters.jsconnect()에 두 개의 인수를 제공합니다. 따라서 후크도 useSelector()useDispatch()를 함께 사용해야합니다.

src/components/VisibilityFilters.js
// import { connect } from 'react-redux';
import { useSelector, useDispatch } from 'react-redux';

// const VisibilityFilters = ({ activeFilter, setFilter }) => {
const VisibilityFilters = () => {
    const activeFilter = useSelector(state => state.visibilityFilter);
    const dispatch = useDispatch();
    return (
        <div className='visibility-filters'>
            {Object.keys(VISIBILITY_FILTERS).map(filterKey => {
                const currentFilter = VISIBILITY_FILTERS[filterKey];
                return (
                    <span

                        onClick={() => {
                            // setFilter(currentFilter);
                            dispatch(setFilter(currentFilter));
                        }}
                    >
                        {currentFilter}
                    </span>
                );
            })}
        </div>
    );
};

/* const mapStateToProps = state => {
    return { activeFilter: state.visibilityFilter };
};
export default connect(
    mapStateToProps,
    { setFilter }
)(VisibilityFilters); */
export default VisibilityFilters;

이상으로 React Redux 공식 「Basic Tutorial」의 작례가, 훅을 사용한 순수한 함수 컴퍼넌트에 재작성할 수 있었습니다. 완성은 CodeSandbox에 「Todo App with Redux using Hooks」로서 공개했습니다.

>> Todo App with Redux using Hooks

좋은 웹페이지 즐겨찾기