src/modules/service.js 에서 액션 타입, 액션 함수를 설정한다.
const INSERT = "service/INSERT"; //액션함수의 타입 설정
const DELETE = "service/DELETE"; //액션함수의 타입 설정
let id = 2;
export const receiveService = data => {
return {
type: INSERT,
payload: {
name: data[data.length - 1].name,
phone: data[data.length - 1].phone,
id: id++
}
};
};
//receiveService 라는 액션함수를 만들었다.
//type은 INSERT 이고, payload 로는 name ,phone, id 를 받게 된다.
export const deleteService = data => {
return {
type: DELETE,
payload: data
};
};
//deleteService 라는 액션 함수이다.
const initialstate = {
data: [
{
name: "김영준",
phone: "010-2277-7337",
id: 1
}
]
};
//초기 state 에는 다음과 같이 들어갈 것이다.
export default function serviceReducer(state = initialstate, action) {
if (action.type === INSERT) {
return { ...state, data: state.data.concat(action.payload) };
} else if (action.type === DELETE) {
return { ...state, data: state.data.action };
} else return state;
}
// reducer 함수를 만든다.
// state는 initialState 가 들어가고, action이 들어간다.
// 1. TYPE이 INSERT 일 경우(receiveService 함수를 사용했을 때)에는 state의 data 에는 payload 로 받는 값을 concat 함수를 이용해서 추가하는 역할을 한다.
// 2. DELETE일 경우 에는 data가 null 로 표시되게 할 것이다.
hOC(higher Order Component)를 만들어준다. , 위치 : src/hocs/withService.js
import React, { Component } from "react";
import { compose } from "recompose"; //recompose 를 사용한다.
import { connect } from "react-redux";
import { receiveService, deleteService } from "../modules/service";
//receiveService, deleteService 는 위에서 만든 액션함수이다.
export default ComposedComponent => {
class withService extends Component {
render() {
return <ComposedComponent {...this.props} />;
}
}
const mapStateToProps = state => ({
service: state.service
});
const mapDispatchToProps = dispatch => ({
serviceAction: {
receiveService: service => dispatch(receiveService(service)),
deleteService: () => dispatch(deleteService())
}
});
return compose(connect(mapStateToProps, mapDispatchToProps))(withService);
};
참조
HOC 의 원리는, 파라미터로 컴포넌트를 받아오고, 함수 내부에서 새 컴포넌트를 만든 다음에 해당 컴포넌트 안에서 파라미터로 받아온 컴포넌트를 렌더링하는 것입니다.
src/container/serviceContainer.js
import React from "react";
import withService from "../hocs/withService";
import { compose } from "recompose";
import ServiceView from "../components/ServiceView";
const ServiceContainer = props => {
return (
<div>
<ServiceView {...props} />
</div>
);
};
const wrappedService = compose(withService)(ServiceContainer);
export default wrappedService;
--> container파일에서 view component 를 감싸고 있는다.
compose 로 withService
를 serviceContainer 에 props로 넘겨받은 다음, 다시 props 로 ServiceView 로 넘겨준다.
src/components/ServiceView.js
import React, { useState } from "react";
const ServiceView = props => {
console.log(props);
const [name, setName] = useState(null);
const [phone, setPhone] = useState(null);
const _handlerName = e => {
if (e.target.name === "name") {
setName(e.target.value);
} else {
setPhone(e.target.value);
}
};
const _addContact = e => {
e.preventDefault();
let profileData =
props.service.data &&
props.service.data.concat({
name: name,
phone: phone
});
let emptyData = { name: "김영준", phone: "010-2277-7337" };
const _setValue =
props.service.data === undefined ? emptyData : profileData;
props.serviceAction.receiveService(_setValue);
};
const _deleteContact = e => {
e.preventDefault();
props.serviceAction.deleteService();
};
return (
<div>
{props.service && props.service.data && props.service.data ? (
props.service.data.map((e, index) => (
<div key={index}>
<button>이름</button>: {e.name}
<button>연락처</button> : {e.phone}
</div>
))
) : (
<div>값이 없습니다.</div>
)}
<hr />
<form>
<input onChange={_handlerName} name="name" />
<input name="phone" onChange={_handlerName} />
<button onClick={_addContact}>추가</button>
<button onClick={_deleteContact}>삭제</button>
</form>
</div>
);
};
export default ServiceView;
console.log 를 찍어보면 위와 같이 나오게 되는데, service 에는 state 의 값이 들어있고, serviceAction 에는 액션 함수가 들어있다.
이제 props로 받아온 withService에서 주는 값을 이용해서 redux 에 추가할 수 있다.