๐์ด์ ๊ธ๊ณผ ์ด์ด์ง๋ ๊ธ์ ๋๋ค.
5. MeinputPage & YouinputPage - 2,3๋ฒ์งธ ํ๋ฉด & ๋ชจ๋ฌ
๐ฅ MeinputPage - ๋์ ์ ๋ณด ์ ๋ ฅ ํ๋ซํผ
<๊ธฐ๋ฅ ๊ตฌํ>
- ์ ๋ ฅํ ์ ๋ณด โฉ ๋ฆฌ๋์ค ์คํ ์ด์ ์ ์ฅ
- ์ฑ๋ณ Click โฉ ๋ ์ค ํ๊ฐ๋ง ํด๋ฆญ ๊ฐ๋ฅ
- ์ธํ์ฐฝ ๊ณต๋ฐฑ โฉ ๋ค์ํ์ด์ง๋ก ๋์ด๊ฐ ์ ์์
- ํ์กํ & MBTI Click โฉ ๋ชจ๋ฌ์ฐฝ์์ ์ ํํ ๊ฐ์ผ๋ก ์ ๋ ฅ(์ง์ ์ ๋ ฅ ๋ถ๊ฐ)
- ๋ค์์ผ๋ก Click โฉ ๋ค์ํ์ด์ง ์ด๋ (์ ๋ณด ๋ชจ๋ ์ ๋ ฅ์)
๐ฅ MeinputPage์ ์ ๋ ฅ๊ฐ ๋ค์ด๊ฐ state ๋ง๋ค๊ธฐ
//MeinputPage.jsx
import React, { useState } from "react";
const MeinputPage = () => {
const [name, setName] = useState("");
const [gender, setGender] = useState("");
const [born, setBorn] = useState("");
const [blood, setBlood] = useState("");
const [mbti, setMbti] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
};
return(
<>
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="๋ด์ด๋ฆ">๋ด ์ด๋ฆ</label>
<input type="text"
placeholder="์ด๋ฆ์ ์
๋ ฅํด์ฃผ์ธ์"
onChange={(e) => {
setName(e.target.value);
}}
/>
</div>
<div className="line" />
<div className="genderType">
<label htmlFor="์ฑ๋ณ" className="genderTitle">์ฑ๋ณ </label>
<input type="radio" className="radioInput" value="male" name="gener" onChange={(e) => setGender(e.target.value)} />
<label htmlFor="๋จ" className="labelGender">
<span>๋จ</span>
</label>
<input type="radio" className="radioInput" value="female" name="gener" onChange={(e) => setGender(e.target.value)} />
<label htmlFor="์ฌ" className="labelGender">
<span>์ฌ</span>
</label>
</div>
<div className="line" />
<div>
<label htmlFor="์๋
์์ผ">์๋
์์ผ</label>
<input type="text" placeholder="8์๋ฆฌ๋ฅผ ์
๋ ฅํด์ฃผ์ธ์" value={born} maxLength="8" onChange={(e) => setBorn(e.target.value)} />
</div>
<div className="line" />
<div>
<label htmlFor="ํ์กํ">ํ์กํ</label>
<input type="text"
placeholder="ํ์กํ์ ์
๋ ฅํด์ฃผ์ธ์"
value={blood}
onChange={(e) => setBlood(e.target.value)}
onClick={() => {
setBloodModal(!bloodModal);
}}
readOnly
/>
</div>
<div className="line" />
<div>
<label htmlFor="mbti">MBTI</label>
<input type="text"
placeholder="MBTI๋ฅผ ์
๋ ฅํด์ฃผ์ธ์"
value={mbti}
onChange={(e) => setMbti(e.target.value)}
onClick={() => {
setMbtiModal(!mbtiModal);
}}
readOnly
/>
</div>
<div className="line" />
</form>
</>
)}
- onChangeํจ์๋ฅผ ํตํด ์ธํ์ฐฝ์ ์ ๋ ฅ๋๋ ๊ฐ์ผ๋ก ๊ฐ state๋ฅผ ๋ณ๊ฒฝํ ์ ์๊ฒ ํด์คฌ์.
- form์ hadleSubmitํจ์๋ฅผ ์ ์ฉ์์ผ์ ์๋์ผ๋ก ์ ์ถ๋๋ ๊ฒ์ ๋ฐฉ์ง์์ผ์คฌ์.
๐ท ์ ๋ ฅํ ์ ๋ณด โฉ ๋ฆฌ๋์ค ์คํ ์ด์ ์ ์ฅ
$ npm install react-redux
1) src ํด๋์ redux ํด๋๋ฅผ ๋ง๋ค๊ณ ์๋์ ๊ฐ์ด ํ์ผ์ ์์ฑํด ์ค๋ค.
2) reducer.js
//reducer.js
const initialState = {
meData: [],
youData: [],
};
const reducer = (state = initialState, action) => {
switch (action.type) {
case "ADD_ME_DATA":
return {
...state,
meData: [...state.meData, action.payload],
};
case "ADD_YOU_DATA":
return {
...state,
youData: [...state.youData, action.payload],
};
default:
return state;
}
};
export default reducer;
- meData, youData์ ์ด๊ธฐ๊ฐ์ ๋น๋ฐฐ์ด๋ก ์์ฑํด ์ค๋ค.
- ์ก์ ํ์ ์ด ADD_ME_DATA์ผ ๋๋ meData์ ๊ฐ์ ์ ์ฅํด์ฃผ๊ณ ADD_YOU_DATA์ผ ๋๋ youData์ ๊ฐ์ ์ ์ฅํด์ฃผ๋ ๋ฆฌ๋์๋ฅผ ์์ฑํด ์ค๋ค.
3) index.js
//index.js
import { combineReducers } from "redux";
import reducer from "./reducer";
const reducers = combineReducers({
data: reducer,
});
export default reducers;
4) store.js
//store.js
import { createStore } from "redux";
import reducers from "./index";
import { composeWithDevTools } from "redux-devtools-extension";
export const store = createStore(reducers, composeWithDevTools());
์คํ ์ด๋ฅผ ์์ฑํด์ฃผ๊ณ ๋ฆฌ๋์ ๊ฐ์ ๋ฃ์ด์ค๋ค. composeWithDevTools()๋ redux dev tool์ ์ฌ์ฉํด์ฃผ๋ ค๋ฉด ์จ์ค์ผํ๋ค.
5) src index.js
// src index.js
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import App from "./components/App";
import reportWebVitals from "./reportWebVitals";
import { Provider } from "react-redux";
import { store } from "../src/redux/store";
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
<App />{" "}
</BrowserRouter>
</Provider>,
document.getElementById("root")
);
reportWebVitals();
<Provider>๋ฅผ ์ต์์์ ๊ฐ์ธ์ฃผ๊ณ store๋ฅผ ๋ฃ์ด์ฃผ๋ฉด ์ด์ store์ ๋ด๊ธด ๊ฐ๋ค์ ์ ์ญ์์ ์ฌ์ฉํ ์ ์๊ฒ ๋๋ค.
์ฌ์ฉ ์ ์ ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ด์ฃผ๋ ์ปดํฌ๋ํธ ์์์ dispatch๋ฅผ ํด์ค์ผํ๋ค.
//MeinputPage.jsx
import { useDispatch } from "react-redux";
import React, { useState } from "react";
const MeinputPage = () => {
const dispatch = useDispatch();
const [name, setName] = useState("");
const [gender, setGender] = useState("");
const [born, setBorn] = useState("");
const [blood, setBlood] = useState("");
const [mbti, setMbti] = useState("");
//์ฌ์ฉ์๊ฐ ์
๋ ฅํ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์์ state๋ค
const onClick = () => {
if (name.length !== 0 && gender.length !== 0 && born.length !== 0 && blood.length !== 0 && mbti.length !== 0) {
dispatch({
type: "ADD_ME_DATA",
payload: {
name,
gender,
born,
blood,
mbti,
},
});}
//์ฌ์ฉ์๊ฐ ๊ฐ์ ์
๋ ฅํ์ง ์์์ ๋๋ ๋ฐ์ดํฐ๊ฐ dispatch๋์ง ์๊ฒ ์กฐ๊ฑด๋ฌธ์ ๊ฑธ์ด์ค
return (
<button type="submit" className="blackBtn" onClick={onClick}> ๋ค์์ผ๋ก
</button>
};
๋ค์์ผ๋ก ๋ฒํผ์ ํด๋ฆญํ ๋ ADD_ME_DATA action์ด ๋ฐ์ํ๊ณ ๋ฐ์ดํฐ๋ฅผ ์ฃ๋ ๋์์ด ์ผ์ด๋๊ฒ ํ๋ค. ์ด๋ ๊ฒ ํด์ฃผ๊ณ ๋น์นธ์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ ฅํ๊ณ redux devTool์ ํ์ธํด๋ณด๋ฉด, ๋ฐ์ดํฐ๊ฐ ์ ์ ์ฅ๋์ด ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
๐ท์ฑ๋ณ Click โฉ ๋ ์ค ํ๊ฐ๋ง ํด๋ฆญ ๊ฐ๋ฅ
๋งค์ฐ ๊ฐ๋จํ๊ฒ ํ ์ ์๋ค. ์ผ๋จ, input radio๋ฅผ ํตํด ์ ํ๋ฒํผ์ ์์ฑํด ์ค๋ค. name๊ฐ์ "gener" ๋ผ๊ณ ์จ์ฃผ๋ฉด ๋ ์ค ํ๊ฒ๋ง ์ ํ ๋ ์ ์๊ฒ ๊ตฌํ ํ ์ ์๋ค.
<label htmlFor="์ฑ๋ณ" className="genderTitle"> ์ฑ๋ณ </label>
<input type="radio" className="radioInput" value="male" name="gener" onChange={(e) => setGender(e.target.value)} />
<label htmlFor="๋จ" className="labelGender">
<span>๋จ</span>
</label>
<input type="radio" className="radioInput" value="female" name="gener" onChange={(e) => setGender(e.target.value)} />
<label htmlFor="์ฌ" className="labelGender">
<span>์ฌ</span>
</label>
๐ท ์ธํ์ฐฝ ๊ณต๋ฐฑ โฉ ๋ค์ํ์ด์ง๋ก ๋์ด๊ฐ ์ ์์ / ๐ท ๋ค์์ผ๋กClick โฉ ๋ค์ํ์ด์ง ์ด๋(์ ๋ณด์ ๋ ฅ์)
์์ ์ป๋ onClick ์ด๋ฒคํธ ํจ์์ ๊ธ์์๊ฐ 0์ผ๋ alert์ฐฝ์ด ๋ฐ ์ ์๊ฒ ์กฐ๊ฑด๋ฌธ์ ์ถ๊ฐํด์คฌ๋ค. ๊ทธ๋ฆฌ๊ณ ๋ฒํผ ํด๋ฆญ์ ์๋์ผ๋ก ํ์ด์ง๊ฐ ๋์ด๊ฐ๋ฉด ์๋๋๊น useNavigateํจ์๋ฅผ ์กฐ๊ฑด๋ฌธ ์์์ ์ฌ์ฉํด์คฌ๋ค.
import { useNavigate } from "react-router-dom";
import { useDispatch } from "react-redux";
const MeinputPage = () => {
let navigate = useNavigate();
const dispatch = useDispatch();
const onClick = () => {
if (name.length === 0) {
alert("์ด๋ฆ์ ์
๋ ฅํด์ฃผ์ธ์");
}
if (gender.length === 0) {
alert("์ฑ๋ณ์ ์ ํํด์ฃผ์ธ์");
}
if (born.length === 0) {
alert("์๋
์์ผ 8์๋ฆฌ๋ฅผ ์
๋ ฅํด์ฃผ์ธ์");
}
if (blood.length === 0) {
alert("ํ์กํ์ ์ ํํด์ฃผ์ธ์");
}
if (mbti.length === 0) {
alert("mbti๋ฅผ ์ ํํด์ฃผ์ธ์");
}
if (name.length !== 0 && gender.length !== 0 && born.length !== 0 && blood.length !== 0 && mbti.length !== 0) {
navigate("/youpage");
dispatch({
type: "ADD_ME_DATA",
payload: {
name,
gender,
born,
blood,
mbti,
},
});}
๐ท ํ์กํ & MBTI Click โฉ ๋ชจ๋ฌ์ฐฝ์์ ์ ํํ ๊ฐ์ผ๋ก ์ ๋ ฅ(์ง์ ์ ๋ ฅ ๋ถ๊ฐ)
๋ชจ๋ฌ ์ฐฝ์์ ์ ํ๋ ๊ฐ์ ๋ฐ์์ค๋ ค๋ฉด setState๋ฅผ props๋ก ๋๊ฒจ์ค์ผํ๋ค. BloodModal, MbtiModal์ฐฝ์ ๋ณ๋์ ์ปดํฌ๋ํธ์ ๋ฐ๋ก ์ ์ํ ๋ค์ MeinputPage์ ์ผํญ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํด์ true์ผ๋ ๋ชจ๋ฌ์ด ๋ณด์ด๊ณ false์ผ ๋๋ ๋ณด์ด์ง ์๊ฒ ํด์ค๋ค์, props๋ก BloodModal, MbtiModal์ ํด๋น ๊ฐ์ ๋ฐ์์ฌ state, setState๋ฅผ propsํด์ค์ผ ํ๋ค.
๊ทธ๋ผ ๊ฐ ๋ชจ๋ฌ์ฐฝ์์๋ ํด๋ฆญ์ setState๋ฅผ ํตํด state๋ฅผ ๋ณ๊ฒฝํ ์ ์๊ฒ ์ด๋ฒคํธ๋ฅผ ๋ง๋ค์ด ์ฃผ๋ฉด ๋๋ค.
//MeinputPage.jsx
//๋ชจ๋ฌ ๊ธฐ๋ณธ๊ฐ false๋ก ์ค์
const [bloodModal, setBloodModal] = useState(false);
const [mbtiModal, setMbtiModal] = useState(false);
//1. ์ผํญ์ฐ์ฐ์ ์ฌ์ฉํด์ ๋ชจ๋ฌ true/ false ์ผ ๋ ์กฐ๊ฑด ๋ง๋ค์ด์ฃผ๊ธฐ & propsํด์ฃผ๊ธฐ
{bloodModal === true ? <BloodModal setBloodModal={setBloodModal} setBlood={setBlood} /> : null}
{mbtiModal === true ? <MbtiModal setMbtiModal={setMbtiModal} setMbti={setMbti} /> : null}
//2. input์ฐฝ ํด๋ฆญ์ ๋ชจ๋ฌ์ด ๋์ค๋๋ก ์ค์ &
์ฝ๊ธฐ๋ง ๊ฐ๋ฅํ๊ฒ readOnly๋ฅผ ์จ์ค(์ด๋์ผ ๋ชจ๋ฌ๊ฐ์ ์ง์ ์
๋ ฅํ ์ ์๊ณ ํด๋ฆญ๊ฐ๋ง ๋ค์ด๊ฐ๊ฒ ํ ์ ์์)
<input
type="text"
placeholder="ํ์กํ์ ์
๋ ฅํด์ฃผ์ธ์"
value={blood}
onChange={(e) => setBlood(e.target.value)}
onClick={() => {setBloodModal(!bloodModal);}} readOnly />
<label htmlFor="mbti">MBTI</label>
<input
type="text"
placeholder="MBTI๋ฅผ ์
๋ ฅํด์ฃผ์ธ์"
value={mbti}
onChange={(e) => setMbti(e.target.value)}
onClick={() => {setMbtiModal(!mbtiModal);}} readOnly/>
ํด๋น ํ์กํ์ ํด๋ฆญํ๋ฉด props๋ก ๋ฐ์์จ state๋ฅผ ๋ณ๊ฒฝํ๊ณ , ์๋์ผ๋ก ์ฐฝ์ด ์ข ๋ฃ๋ ๋ค ๊ทธ ๊ฐ์ด ์ธํ์ฐฝ์ ์ ๋ ฅ๋จ.
//BloodModal.jsx
import React from "react";
import styled from "styled-components";
import { ModalBack } from "./IconModal";
let BloodModal = (props) => {
const onClick = () => {
props.setBloodModal(false);
};
return (
<ModalStyle>
<ModalBack>
<div className="BloodModal">
<div className="bloodTitle">ํ์กํ</div>
<div
className="bloodType"
id="A"
onClick={() => {
props.setBlood("A");
props.setBloodModal(false);
}}
>
Aํ
</div>
<div
className="bloodType"
id="B"
onClick={() => {
props.setBlood("B");
props.setBloodModal(false);
}}
>
Bํ
</div>
<div
className="bloodType"
id="O"
onClick={() => {
props.setBlood("O");
props.setBloodModal(false);
}}
>
Oํ
</div>
<div
className="bloodType"
id="AB"
onClick={() => {
props.setBlood("AB");
props.setBloodModal(false);
}}
>
ABํ
</div>
</div>
<div className="modalBack" onClick={onClick}></div>
</ModalBack>
</ModalStyle>
);
};
๐ฅ [๋์ ์ ๋ณด, ์๋ ์ ๋ณด] , [ํ์กํ ๋ชจ๋ฌ, MBTI ๋ชจ๋ฌ] ๋ ๊ฐ๊ฐ ํ๋์ฉ๋ง ์ ๋ฆฌํด๋๋ ค๊ณ ํ๋ค.(์๋ ๋ฐฉ์์ด ์ ์ฌํจ)
6. ResultPage (๋ง์ง๋ง ํ์ด์ง)
<๊ธฐ๋ฅ ๊ตฌํ>
- ์ ๋ ฅํ ์ ๋ณด ์กฐํฉํ ์ ์ ๋์ฐ๊ธฐ
- ์ ๋ ฅํ ์ ๋ณด ์กฐํฉํ ๊ฒฐ๊ณผ ๋์ฐ๊ธฐ
- ๋ค์ํ๊ธฐClick โฉ ์์ ์ ๋ฆฌํ๋ useNavigeteํจ์ ๋์ผํ๊ฒ ์ฌ์ฉ
- ๊ฒฐ๊ณผ๋งํฌ ๊ณต์ Click โฉ mbti(1)ํฌ์คํ ์ ์ ๋ฆฌํด๋ (CopyToClipboard)
๐ท ์ ์ & ๊ฒฐ๊ณผ ๋์ฐ๊ธฐ
Axios post๋ฅผ ํด์ ๋ฐ์์จ ๊ฒฐ๊ณผ๊ฐ์ ์ํ๋ ์์น์ ๋ฟ๋ ค์ฃผ๋ฉด ๋๋๋ฐ
1) redux store์ ์ ์ฅํ๋ ๊ฐ์ useSelector๋ฅผ ํตํด ๊ฐ์ ธ์ค๊ธฐ
//ResultPage.jsx
import axios from "axios";
const ResultPage = () => {
const state = useSelector((state) => state);
}
ํด๋น๊ฐ ์ฝ์์ฐฝ์ ๋์๋ณด๋ฉด, ๋ฐ์ดํฐ๋ฅผ ์ ๊ฐ์ง๊ณ ์จ ๊ฒ์ ํ์ธํ ์ ์๋ค. ์ด ๊ฐ์ API๊ฐ ์๊ตฌํ๋ ํ์์ ๋ง์ถฐ์ postํด์ฃผ๋ฉด ๋๋ค.
useEffect์ ๋น๋ฐฐ์ด์ ๋ฃ์ด์ค์ ๋ฌดํ๋ ๋๋ง์ด ๋ฐ์ํ๋ ๊ฒ์ ๋ง์์ฃผ๊ณ , ๊ทธ์์ axios ์์ฒญ์ ํ๋ค.
๋ฐ์์จ ๋ฐ์ดํฐ๋ฅผ ๋ง๋ค์ด๋ state์ ์ ์ฅํด์ค๋ค. ์ด ๋ฐฉ์์ผ๋ก ํ๋ฉด ์ด์ฉ ์ ์์ด ๊ฐ์ฅ ์ฒ์์ undefined๊ฐ ์ฐํ๊ฒ ๋๋๋ฐ, ๊ทธ๋ฌ๋ฉด undefined์ผ ๋๋ ํ๋ฉด์ ์ถ๋ ฅํ ๊ฐ์ด ์๊ธฐ ๋๋ฌธ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค. ํ๋ฉด์ ์ถ๋ ฅํ ๋ ์กฐ๊ฑด๋ฌธ์ ํ๋ ์์ฑํด์ undefined์ด ์๋ ๋๋ง ๋์์ด ์ผ์ด๋๊ฒ ํด์ค์ผํ๋ค.
const [result, setResult] = useState();
useEffect(() => {
axios
.post("https:// api์ฃผ์๋งํฌ", {
me: state.data.meData[0],
you: state.data.youData[0],
})
.then((res) => {
setResult(res.data.result);
})
.catch((err) => {
console.log(err);
}, []);
return <></>;
}, []);
์ฝ์์ฐฝ์ ํด๋น res ๊ฐ์ ๋์๋ณด๋ฉด, post๋ฅผ ์ฑ๊ณตํ ๊ฒ์ ํ์ธ ํ ์ ์๋ค. ์ด์ ์ด ๋ฐ์ดํฐ๋ค์ ์ํ๋ ์๋ฆฌ์ ๋ฐฐ์นํด์ฃผ๋ฉด ๋๋ค.
์กฐ๊ฑด๋ฌธ ๋ง์กฑ์์๋ง ๋ด๋ถ ๋ด์ฉ์ ์ถ๋ ฅํ๋ ์กฐ๊ฑด๋ฌธ ์์ฑ
const resultContentsBox = () => {
if (result !== undefined) {
return(
//์ถ๋ ฅํ ๋ด์ฉ๋ค ์์ฑ)
}
์ด๋ ๊ฒ ํด์ฃผ๊ณ ResultPage return ๊ฐ์ ํจ์๋ฅผ ์คํํด์ฃผ๋ฉด ๋๋ค.
return (
<>
<ResultStyle>{resultContentsBox()}</ResultStyle>
</>
);
๐ฉ ์คํ์ผ ์ปดํฌ๋ํธ๊น์ง ์์ฑํ ์ต์ข ์ฝ๋ ๐ฝ
https://github.com/codnjs779/chemistry-test.git
GitHub - codnjs779/chemistry-test
Contribute to codnjs779/chemistry-test development by creating an account on GitHub.
github.com
'side project' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[React][side project] mbti๊ถํฉ ํ ์คํธ(3) - aws Amplify ๋ฐฐํฌ & ๊ฐ๋น์ ๋๋ฉ์ธ ๋ถ์ด๊ธฐ (2) | 2021.11.26 |
---|---|
[React][side project] mbti๊ถํฉ ํ ์คํธ(1) (0) | 2021.11.25 |