- Material UI
- Immer
- Redux
- React-Redux
- Redux-Thunk
- Axios
- Redux Dev Tool
- Redux Logger
- React Router
- ๊ณต์ ๋ง์คํฌ ์ฌ๊ณ API
- NaverMapAPI
- Check where masks are sold on the map
- Check the details of where masks are sold
- Reducer / Redux / React-Redux / Redux-thunk / Redux-logger store๋ฅผ provider์
- React-Router ํตํด Page Switch
- AppBar, BottomNavigation
- ListUI
- Map Page
- NaverMap -> Component
- Map - Redux ์ฐ๊ฒฐ
- Map์ Marker ์ถ๊ฐ (iconfinder์ด์ฉ)
- ๋งต์ ์์ง์ธ ๋ค์์ ํ์ฌ ์ค์ฌ์์ ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐ๋ก ๊ฐ์ ธ์ค๊ธฐ
- ์ฌ๊ณ list ์ ๋ ฌ
- ์์ ์์ธ ํ์ด์ง
- ๋งต ๋ง์ปค์์ ์์ธ ํ์ด์ง ์ฐ๊ฒฐ
- responsiveํ๊ฒ ์๋จ padding ํฌ๊ธฐ๊ฐ ๋ณ๊ฒฝ๋๋๋ฐ, ๋ง์ง ์กฐ์ ใ ใ ๊ธฐ..ใ
- redux-dev-tool์ ๋ง๋๋ ค๋ฉด ์คํ ์ด์ ํด๋น ์ฝ๋๋ฅผ ๋ฃ์ด์ค์ผ ํจ
const store = createStore(
reducer, /* preloadedState, */
+ window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
๋ฏธ๋ค์จ์ด๋ ๊ฐ์ด ์ธ ๊ฒฝ์ฐ๋?
import { createStore, applyMiddleware, compose } from 'redux';
+ const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
+ const store = createStore(reducer, /* preloadedState, */ composeEnhancers(
- const store = createStore(reducer, /* preloadedState, */ compose(
applyMiddleware(...middleware)
));
์ ์ฉ๊ฒฐ๊ณผ!
reducers/index.js์ baseState์ ๊ฐ์ ๋ฃ์ด๋ณด๊ณ
redux-dev-tool chrome ์์ ํ์ธ
- css ์ ์ฉ
"& .MuiBottomNavigationAction-root" ์ด ํ๊ทธ๋ฅผ ๋ง๋๋ฉด css๋ฅผ ๋ณ๊ฒฝ์์ผ์ค ์๋ ์์
const useStyles = makeStyles({
root: {
background: "#eee",
width: "100%",
"& .MuiBottomNavigationAction-root": {
minWidth: 0
}
},
});
- useState
const [value, setValue] = React.useState(() =>{
const path = location.pathname;
//pathname์ URL์ ๊ฒฝ๋ก ์ด๋ฆ์ ์ค์ ํ๊ฑฐ๋ ๋ฐํํฉ๋๋ค.
if (path === "/list") return 1;
if (path === "/help") return 2;
if (path === "/about") return 3;
return 0;
});
ํ์ฌ ๋๊ฐ ์ ํ๋์ด์๋์ง๋ valueState๋ฅผ ํต์ ํ๊ณ ์๋ค. hooks์ ์ด์ฉํด์ ํ ์ ์ฐ๊ณ ์๋ค. ์ด๊ธฐ๊ฐ์ด 0์ด๋ผ์ ๋ฌด์กฐ๊ฑด 0๋ฒ์งธ๊ฐ ์ ํ๋์ด์ ๋งํฌํ์ด์ง๊ฐ ๋ฐ๋์ด๋ map์ ๊ณ ์ ๋์ด ์๋ค. ์ฌ๊ธฐ์ ์ด๊ธฐ๊ฐ์ path๋ฅผ ์ ํํด์ค์ผ ํ๋๋ฐ... react-router-dom์ hooks ์ฐธ๊ณ ! useLocation, ์ด๊ธฐ๊ฐ์ ํจ์๋ก ๋ฃ์ด์ฃผ๋ ๊ฒ์ด ์ข๋ค. ์ด๊ธฐ๊ฐ์ด ํจ์๋ก ๋์ด์์ง ์์ผ๋ฉด ์ฑ์ ๋๋๋ง ํ ๋๋ง๋ค ์คํ์ ํด์ผ ํ๋ค. ๊ทธ๋งํผ ์์ข์ ์ ์ด ์๊น..
useState์๋ intinalState๊ฐ ๋ค์ด๊ฐ๋๋ฐ intinalState๊ฐ ํจ์๋ฉด ์ด ํจ์๊ฐ ์ ์ผ ์ฒ์ ์ฝํ ๋ ํ๋ฒ๋ง ์ฝํ๊ณ ๊ธฐ์ต์ด ๋๋ค?....
json ํ์ผ์ js object๋ก ๋ฐ๊ฟ์ค
- ๋ฐ์์ ๋ค์ด์์ผ๋ฏ๋ก ๋ ์ด์ ์๋ฌ๋ผ๊ณ ํ์ํด์ฃผ์ง ๋ง์ธ์...!
/* global naver */
- css ๋ด์์ ์ง์ ๊ณ์ฐ์ ํ ์ ์๋๋ก ํด์ฃผ๋?!
const useStyles = makeStyles((theme) => ({
mapWrapper: {
width: "100%",
marginBottom: theme.spacing(7),
height: `calc(100vh - ${ 2 * theme.spacing(7)}px)`
},
}));
๊ธฐ๊ณ ํ๋ฉด๋ง๋ค ์ฌ์ด์ฆ๊ฐ ๋ฌ๋ผ์ง๊ธฐ ๋๋ฌธ์ ์กฐ์ ์ ํด์ค์ผ ํ๋คใ ใ
- What is ... ?
The ... can also be used to spread objects and not just arrays
// Using rest syntax here
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x; // 1
y; // 2
z; // { a: 3, b: 4 }
// Using spread here
let n = { x, y, ...z };
n; // { x: 1, y: 2, a: 3, b: 4 }
- action์ ์ถ๊ฐ,,์ด๋ ๊ฒ ๋ณด์ด๋ ์ด์ ๋ ๋ฆฌ๋์ค ๋ก๊ทธ๋ฅผ ๋ฐ์๋จ๊ธฐ ๋๋ฌธ..!
ํ์ง๋ง ์์ง state๋ ๋ฐ๋์ง ์์ reducer์์ ์ฒ๋ฆฌ๋ฅผ ์ํด์คฌ๊ธฐ ๋๋ฌธ์ใ ใ
- ํฐ ๋ฌธ์ ๊ฐ?...
const reducer = produce((state, action) => {
switch(action.type) {
case "SET_MAP_ZOOM":
state.mapZoom = action.payload;
break;
case "SET_MAP_CENTER":
state.mapCenter = action.payload;
break;
// ์ ์ฒด global state๋ฅผ ๋ฐ๊ฟ์ค ๊ฒ..!
default:
break;
}
}, baseState);
์ ์๊ธธ ์ ์๋๋ฉด...
์ด๋ ๊ฒ ๋๋๊ฐ ๋๋ฒ ๋จผ์ ๋ถ๋ฆฌ๋ฉด ์๊ด์ด ์๋ค. ์ฒ์ ๋๋๊ฐ ๋์์ ๋๋ ๋ง์ดํธ ๋๊ธฐ ์ , ๋ฆฌ๋์ค ๊ฐ์ด. ๋ฐ๋์ง ์์, ๋ฐ๋ผ์ ๋๋ ํ Map์ด initialized ๋๋ ๊ฒ์ ์ข์..๊ทผ๋ฐ ์ง๊ธ ์ํ์์ ๋๋๊ทธ ํด์ ์ฎ๊ธฐ๋ฉด ๊ณ์ ๋๋๊ฐ ๋ฐ์ํ๋ค. Map์ด initialized๋๋ฉด ๋ฌธ์ ๊ฐ ์๊น ใ -> ํ์ด์ง ๋ฐ๊ฟ ๋๋ง๋ค initialized ๋จ
- ์ง๊ธ์.. ์ง๊ธ์ pin์ stores์ 100๋ง๊ฐ๋ฅผ ๋ฐ์์์ผ๋ฉด ๋ฐฑ๋ง๊ฐ๋ฅผ ๋ง์ปค๋ก ์ฐ๊ณ ์๋ค. ๊ทผ๋ฐ ๊ทธ๋ด ํ์ ์์..ใ ใ ๋ฐ์ด๋ ์์ (=๋งต ํ๋ฉด) ์๋ ๊ฒ๋ค๋ง ์ฐ๋ ๊ฒ ์ข๋ค -> getBounds,,,,,,
hasLatLng(latlng)
๊ฐ์ฒด์ ์ขํ ๊ฒฝ๊ณ ๋ด์ ์ง์ ํ ์ขํ๊ฐ ์๋์ง ์ฌ๋ถ๋ฅผ ํ์ธ!
์์ ๊ฐ์ด ๋ค๋ฅธ ๊ณณ์ ์์นํ ๊ณณ์ ๋ง์ปค๋ ๋ํ๋์ง ์์! ๊ทผ๋ฐ ๋จ์ ์กด์ฌ ใ ๋ค๋ฅธ ๊ณณ์ ์์นํ ๊ณณ์ ์คํ ์ด๋ฅผ ๊ฐ์ง๊ณ ์์์๋ ๋ถ๊ตฌํ๊ณ ๋์ค์ง ์๋ ๊ฒ..naver.maps.Event.addListener(this.map, 'dragend', () => {
const coord = this.map.getCenter();
dispatch(setMapCenter([coord.lat(), coord.lng()]));
this.loadPins();
// dragend๊ฐ ๋์์ ๋ ๋ค์ loadPins ํด์ค์ผ ํ ํ์๊ฐ ์๋ค. ๊ทธ ์์ ํ๋ค์ ๋ค์ ๋ถ๋ฌ๋ด์ฃผ๋๋ก!
});
this.loadPins(); ์ถ๊ฐํ๊ธฐ ๊ทผ๋ฐ ์ฌ์ ํ ๋ฌธ์ ์กด์ฌ, ์ด๋ฏธ ์๋ marker๋ฅผ ๋ ๋ง๋ค๊ณ ์์ ๊ฒ์ด๋ค.
if (this.markers[store.code]) {
// code์ ํด๋นํ๋ ๋ง์ปค๊ฐ ์์ผ๋ฉด ๋ ํ ํ์๊ฐ ์์ผใ
,,๋น ์ ธ๋๊ฐ๋ฉด ๋จ
return;
}
์ด ๋ถ๋ถ์ ์ถ๊ฐํด์ฃผ๋ฉด์ ํด๊ฒฐ
- stores๊ฐ ๋ณ๊ฒฝ ๋ฌ๋๋ฐ ์ ์๋ฌด๊ฒ๋ ํ๋ฉด์ ๋ํ๋์ง ์์๊น?...stores๊ฐ ๋ณํ๋ฉด ๋ ๋๊ฐ ๋ ๊ฒ์ด๋ค. ๊ทผ๋ฐ ๋ ๋๊ฐ ๋ ์ดํ ์๋ฌด๊ฒ๋ ๋ณํ์ง ์์
render() {
console.log("RENDER~~~~~~~")
return (
<MapDiv ref={this.mapRef}/>
/* ์ด๋ ๊ฒ id๋ฅผ ์ฃผ๋ฉด ์ปดํฌ๋ํธ๋ค๋ก์์ ์ญํ ์ ํ ์ ์๋ค.
๋ฆฌ์กํธ์ refs๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ์์ผ๋ก!
*/
)
}
-
์๋ก ํจ์น๋ฅผ ํด์์ผ ํ ํ์๊ฐ ์๋๋ฐ ํจ์น๊ฐ ์๋๊ฑฐ๊ณ stores๋ ๊ทธ๋ฐ ๊ฒ๋ค์ด ๋ฐ๋์์ ๋ ๊ทธ๊ฑฐ์ ๋ํด์ ๋ฐ์์ ์ํ๊ณ ์๋ค. ๋ ๋์๊ฒ๋ค ์ด๊ฒ์ ๋ฃ๊ธฐ ๋ณด๋ค๋...
-
ํ์ฌ์ center์์ ์๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ์ ๋ง๋ค์
-
ํจ์น๋ฅผ ์ํ๊ธฐ ๋๋ฌธ์ stores์ ์๋ฌด๊ฒ๋ ์์
-
store๋ฅผ ์ง์ ๋ฃ์ด์ฃผ๋ ค๊ณ ํ๋ค. ์คํ ์ค์ useSelector์ฐ๊ฒฐ ํ๋ ๋ถ๋ถ ๋นผ์ฃผ๊ณ ใ