React.js(12) - react-redux, react-cookies
๐ฉ๐ react - redux
- redux์ react๋ฅผ ์ฐ๋ํด์ ์ฌ์ฉํ๊ธฐ ํธ๋ฆฌํ๋๋ก ๋ง๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค.
- store์ ํ์ ์ปดํฌ๋ํธ์ ๋งค๋ฒ ์์ํ์ง ์๊ณ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, ์คํ ์ด ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๊ณ ๋ณ๊ฒฝํ๋ ์ฝ๋๋ฅผ ๋ชจ๋ํํ์ฌ ์ปดํฌ๋ํธ ๋ด์ ์ค๋ณต๋ ์ฝ๋ ์ฌ์ฉ์ ์ต์ํํ๋ ๊ฒ์ด ๊ฐ๋ฅํ๋ค.
- react-redux์ ๋ฐ์ดํฐ ๋ณ๊ฒฝ ๊ณผ์ : ์คํ ์ด โก ์ปดํฌ๋ํธ โก ์ก์ โก ๋ฆฌ๋์ โก ์คํ ์ด
- ์คํ ์ด โก ์ปดํฌ๋ํธ ๊ณผ์ ์์ connect๋ผ๋ react-redux ๋ด์ฅ ํจ์๊ฐ ์ฌ์ฉ๋๋ค.
- ์ปดํฌ๋ํธ โก ์ก์ ๊ณผ์ ์์ connect๋ผ๋ react-redux ๋ด์ฅ ํจ์๊ฐ ์ฌ์ฉ๋๋ค.
โ react-redux ์ค์นํ๊ธฐ
npm install --save react-redux
๐ src ํด๋ ํํ
โ index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import {createStore} from 'redux'; //redux์์ ๋ฐ์ดํฐ ๋ณ๊ฒฝ์ ํ์ํ ํจํค์ง ๊ฐ์ ธ์ค๊ธฐ
import {Provider} from 'react-redux';//react-redux์์ react-redux ์ฐ๊ฒฐ์ ํ์ํ ํจํค์ง ๊ฐ์ ธ์ค๊ธฐ : store ์์์ ํ์ํ ํจํค์ง์
import reducers from './reducers';
const store = createStroe(reducers);
const listener =()=>{
ReactDOM.render(
<Provider> //Provider ์ ๋ฐ์ดํฐ๋ฅผ ๋๊ฒจ์ฃผ๋ฉด ์ค๊ฐ ์ปดํฌ๋ํธ์์ Props ๊ฐ์ ๋ค์ ์ ๋ฌํด์ค ํ์์์ด ๋ชจ๋ ํ์ ์ปดํฌ๋ํธ์์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด๊ฐ๋ฅํจ
<App indexProp="react"/> //App ์ปดํฌ๋ํธ์์ ์ฌ์ฉํ ๋ณ์ indexProp์ ๊ฐ์ ํ ๋นํด์ App์ props์ผ๋ก ์ ๋ฌํด์ค๋ค.
</Provider>,
document.getElementById('root')
);
};
store.subscribe(listener);
listener();
- <Provider></Provider>๋ก ๊ฐ์ธ์ธ Props ๊ฐ๋ค์ ๋ชจ๋ ์ปดํฌ๋ํธ์์ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
๐จConnect ์ฌ์ฉํ๊ธฐ
โ App.js
import React from "react";
import { Component } from "react";
import {Connect} from 'react-redux;' //react-redux ํจํค์ง์์ connect ํจ์๋ฅผ ์ํํธํ์ฌ ์ฌ์ฉํ ์ ์๋๋กํจ
import StrAddButton from "../StrAddButton";
class App extends Component { //App class : ํ๋ฉด์ ๋ ๋๋ง๋ ๋ด์ฉ์ ์ ์
render() {
return (
<div>
<h1>Start React</h1>
{/* <span>{this.props.store.getState().data.str}</span><br/>*/}
<span>{this.props.str}</span><br/> //span ํ๊ทธ๋ก props์์ ๋ฐ์์จ str ๊ฐ์ ํ์ํ๋๋ก ํ๋ ๊ฒ
{/*<StrAddButton store = {this.props.store}/> */}
<StrAddButton AppProp="200"/>
</div>
);
}
}
let mapStateToProps = (state, props) =>{
console.log('Props from index.js :' + props.indexProp)
return {
str : state.data.str,
};
};
App = Connect(mapStateToProps, null)(App); //import ํ ๋ค์ ๊ฐ์ฅ ๋จผ์ ์ ์ด์ฃผ์ด์ผ ํ๋ค.
export default App;
๐ Connect ํจ์ ์ฌ์ฉํ๊ธฐ
App = Connect(mapStateToProps, null)(App);
- App ์ปดํฌ๋ํธ๋ฅผ Connect(mapStateToProps, null)(App) ํ์์ผ๋ก ์ฐ๊ฒฐํ์ฌ ๋ด๋ณด๋ธ๋ค. ์ด๋ฅผ ํตํด App ์ปดํฌ๋ํธ์์ Redux์ state ๊ฐ์ props๋ก ์ฌ์ฉํ ์ ์๊ฒ ๋๋ค.
- ์๋ Connect(mapStateToProps, mapDispatchToProps)์ธ๋ฐ ์ฌ๊ธฐ์๋ mapStateToProps๋ง ์คํ๋๋ฏ๋ก ๋ ๋ฒ์งธ ์ธ์๋ ๋น์ฐํ null์ด ๋๋ค.
mapStateToProps ํจ์ ์ ์ํ๊ธฐ
- index.js์ App.js๋ฅผ ์ฐ๊ฒฐํด์ฃผ๋ ์ปดํฌ๋ํธ์ ํจ์๋ผ๊ณ ์๊ฐํ์!
let mapStateToProps = (state, props) =>{
console.log('Props from index.js :' + props.indexProp)
return {
str : state.data.str,
};
};
- state์ props๋ฅผ ๋ฐ๋๋ฐ state๋ ์ฌ๊ธฐ์ ์คํ ์ด์ state์ด๊ณ props๋ ๋ถ๋ชจ ์ปดํฌ๋ํธ์์ ์ ๋ฌ๋ฐ์(App์ ๋ถ๋ชจ์ปดํฌ๋ํธ๋ index.js) props๋ฅผ ์ ๋ฌ๋ฐ์ App ์ปดํฌ๋ํธ์ ํจ์์์ ์ฌ์ฉํ ์ ์๋๋ก ํ๋ ์ ์ด๋ค.
- ์์ props๋ index.js์์ ์ ๋ฌ๋ฐ์ props.indexProps = "react"์ด๋ฏ๋ก react๊ฐ console.log์ ํตํ์ฌ ์ถ๋ ฅ๋๋ฉฐ, (props ์ฒ๋ฆฌ ๋ถ๋ถ) store๋ ์คํ ์ด์ state ๋ณ์ str ๋ณ์๊ฐ์ผ๋ก ํ ๋น๋์ด ๋ฐํ๋๋ค.
๐ {this.props.str}
<span>{this.props.str}</span><br/>
- return {str : state.data.str, };๋ก ๋ฐ์์จ ์คํ ์ด ๋ฐ์ดํฐ๋ฅผ App ์ปดํฌ๋ํธ์ props์ str ๋ณ์๋ก ํ ๋นํ์ฌ ์ถ๋ ฅํด์ค๋ค.
<StrAddButton AppProp="200"/>
- StrAddButton ์ปดํฌ๋ํธ์์ ์ฌ์ฉํ ๋ณ์ AddProp์ 200 ๋ฌธ์์ด์ ํ ๋นํด props๋ก ์ ๋ฌํ๋ค.
๐ฉ๐ป Dispatch ํจ์
- ์ปดํฌ๋ํธ๊ฐ ์คํ๋๋ฉด ๋ฐ์ธ๋ฉ๋dispatch ํจ์๊ฐ ์คํ๋๊ฒ ๋๋ค.
- Redux store์ action ๊ฐ์ฒด๋ฅผ ์ ๋ฌํ์ฌ ์ํ ๋ณํ๋ฅผ ๋ฐ์์ํด
- Action์ Store์ ์ ๋ฌํ์ฌ ํด๋น Action์ ๋ฐ๋ฅธ ์๋ก์ด ์ํ๋ฅผ ๋ง๋ค์ด ๋ธ๋ค. ์ดํ, ํด๋น ์๋ก์ด ์ํ๊ฐ ์ปดํฌ๋ํธ์ ์ ๋ฌ๋์ด UI๋ฅผ ์ ๋ฐ์ดํธํ๋ค.
โ StrAddButton.js
- Redux store์ ์๋ก์ด ๋ฌธ์์ด์ ์ถ๊ฐํ๊ณ ์ ๋ฐ์ดํธํจ
import React, {Component} from 'react';
import {add} from './actions'; // ์ก์
์์ฑ์ ํจ์๋ฅผ import : add()
import {Connect} from 'react-redux;' // react-redux ํจํค์ง์์ connect ํจ์๋ฅผ ์ํฌํธํด์์ React์ Redux ์ฐ๊ฒฐ
class StrAddButton extends Component {
render() {
return (
// <input value = 'Add200' type = "button" onClick = {this.addString}/>
<input value = "200" type = "button" onClick = {this.props.addString} />
)
// ๋ฒํผ ํด๋ฆญ ์ ๋ฌธ์์ด์ด ์ถ๊ฐ๋๋ ํจ์ : addtring
}
// addString =()=>{
// this.props.store.dispatch(add());
// }
}
let mapDispatchToPRops = (dispatch, props) =>{
console.log('Props from App.js : ' + props.AddProp)//๋ถ๋ชจ ์ปดํฌ๋ํธ์ธ App์์ ๋ฐ์์จ Prop์ ์ถ๋ ฅํด์ค๋ค.
return {
addString : () => dispatch(add()) //dispatch ํจ์๋ฅผ ์ปดํฌ๋ํธ ๋ด ํจ์์ธ addString์ ๋ฐ์ธ๋ฉํ๊ณ , addStringํจ์๋ Props์ ํ ๋น๋จ
//๊ธฐ์กด์ addString ํจ์๋ dispatch ํจ์๋ฅผ ํธ์ถํ๊ธฐ ์ํด ์๋ก์ด ํจ์๋ฅผ ์ ์ธํ์ง๋ง, ์ฐ๋ฆฌ๋ ๊ธฐ์กด์ ๋ ํจ์๋ฅผ ๋ฐ์ธ๋ฉํ๊ธฐ ๋๋ฌธ์ ๋ณ๋ ํจ์์ ์ธ์ ๋ถํ์ํจ
// ๋ค์๊ณผ ๊ฐ๋ค. const addString=()=> dsipatch(add())
};
};
StrAddButton = Connect(null, mapDispatchToPRops)(StrAddButton); //connectํจ์์์๋ ์ฒซ ๋ฒ์งธ ์ธ์๋ฅผ ๋ณด์ง๋ง๊ณ ๋๋ฒ์งธ ํ๋ผ๋ฏธํฐ๋ง ๋ณด์
export default StrAddButton;
๐ addString()
- store.dispatch() ๋ฉ์๋ : Action์ Store์ ์ ๋ฌํ์ฌ ํด๋น Action์ ๋ฐ๋ฅธ ์๋ก์ด ์ํ๋ฅผ ๋ง๋ค์ด๋ด๋๋ฐ, ์ฌ๊ธฐ์์ action์ add()ํจ์์ด๋ค. ๋ฐ๋ผ์ add() ํจ์๊ฐ props์ธ Stroe๋ก ์ ๋ฌ๋๊ฒ ๋๋ค. โก Redux store์ dispatch() ๋ฉ์๋๋ฅผ ํตํด ํธ์ถ๋์ด Redux state๋ฅผ ๋ณ๊ฒฝํจ
๐ mapDispatchToProps
- dispatch ํจ์๋ฅผ ์ปดํฌ๋ํธ ํจ์์ ๋ฐ์ธ๋ฉํจ ์ฆ, ์ปดํฌ๋ํธ๊ฐ ์คํ๋๋ฉด ๋ฐ์ธ๋ฉ๋ dispatch ํจ์๊ฐ ์คํ๋๊ฒ ๋๋ค.
- ๋ฆฌ๋์์ ์ก์ ์ ์ ๋ฌํ๋ ํจ์์ธ dispatch๋ฅผ ์ธ์๋ก ๋ฐ์ ์ฌ์ฉํ๋ค.
- StrAddButton ์ปดํฌ๋ํธ๋ฅผ Redux์ ์ฐ๊ฒฐํ๋ ์น๊ตฌ๋ผ๊ณ ์๊ฐํ๋ฉด ๋จ
- dispatch ํจ์๋ฅผ props๋ก ๋งคํํด์ฃผ๊ณ ์ก์ ์ dispatchํด์ฃผ๋ ํจ์๋ฅผ ์์ฑํด์ค๋ค.
๐ redux ๋ฏธ๋ค์จ์ด
- ์ก์ ์ dispatch ํจ์๋ก ์ ๋ฌํ๊ณ ๋ฆฌ๋์๊ฐ ์คํ๋๊ธฐ ์ ๊ณผ ์คํ๋ ํ์ ์ฒ๋ฆฌ๋๋ ๊ธฐ๋ฅ
- redux ํจํค์ง์์ ์ง์ํ๋ applyMiddleware ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฏธ๋ค์จ์ด๋ฅผ ๊ตฌํํ ์ ์๋ค.
โ index.js
import React from "react";
import { ReactDOM } from "react-dom";
import './index.css';
import App from './components/App';
import {createStore} from 'redux';
import {Provider} from 'react-redux';
import reudcers from './reducers';
import {applyMiddleware} from 'redux';
const CallMiddleware = store => nextMiddle => action => {
console.log('1. reducer ์คํ ์ ');
console.log('2. action.type : ' + action.type+', store str: ' + store.getState().data.str);
let result = nextMiddle(action);
console.log('3. reducer ์คํ ํ');
console.log('4. action.type : ' + action.type + ', store str :' + store.getState().data.str );
return result;
}
const store = createStore(reudcers, applyMiddleware(CallMiddleware));
const listener =() =>{
ReactDOM.render (
<Provider store= {store} >
<App indexProp = "react"/>
</Provider>,
document.getElementById('root')
);
};
store.subscribe(listener);
listener();
๐ createStore
- store๋ฅผ ์์ฑํจ
- reducer์ ์ฒซ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ๋ก, applyMiddleware์ ๋๋ฒ์งธ ํ๋ผ๋ฏธํฐ๋ก ๋ฐ์์จ๋ค. ์ด๋ applyMiddleware์ CallMiddleware์ ์ธ์๋ก ๋ฐ์์จ๋ค.
const store = createStore(reudcers, applyMiddleware(CallMiddleware));
๐ CallMiddleware ํจ์
- Redux ์คํ ์ด์ ์ํ๋ฅผ ๋ฐ์์ ๋ค์ ๋ฏธ๋ค์จ์ด ํจ์๋ฅผ ์คํํ๋ nextMiddle ํจ์์ ์ก์ ๊ฐ์ฒด๋ฅผ ๋ฐ์์ ๋ค์ ๋ฏธ๋ค์จ์ด ํจ์๋ก ์ก์ ๊ฐ์ฒด๋ฅผ ์ ๋ฌํจ
const CallMiddleware = store => nextMiddle => action => {
console.log('1. reducer ์คํ ์ ');
//store ๋งค๊ฐ ๋ณ์ ์คํ : ๋งค๊ฐ๋ณ์๋ก ๋ฐ์ action ๊ฐ์ฒด์ type ์์ฑ๊ณผ ์คํ ์ด์ ์ํ๋ฅผ ์ถ๋ ฅํด์ฃผ๋์ค์
console.log('2. action.type : ' + action.type+', store str: ' + store.getState().data.str);
//store ๋งค๊ฐ๋ณ์ ์คํ ํ nextMiddleware ์คํ
// ๋ค์์ ๋ฏธ๋ค์จ์ด ํจ์ ํน์ ๋ฆฌ๋์ ํจ์ ์คํ : ๋ค์์ ์ก์
์คํ
let result = nextMiddle(action);
// ๊ทผ๋ฐ ์ฌ๊ธฐ์๋ ๋ค์์ ์คํํ ๋ฏธ๋ค์จ์ด๊ฐ ์์ผ๋ฏ๋ก ๋ฆฌ๋์๋ฅผ ์คํํจ
console.log('3. reducer ์คํ ํ');
// ๋ฆฌ๋์๊ฐ ์คํํ ์ก์
์ type ๋ณ์์ store์ ์ํ ๋ณ์ str์ ๊ฐ์ ๋ก๊ทธ๋ก ์ถ๋ ฅํจ
console.log('4. action.type : ' + action.type + ', store str :' + store.getState().data.str );
return result;
}
๐ listener()
- Redux ์คํ ์ด์ ์ํ๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค ํธ์ถ๋๋ ํจ์
- ReactDOM.render ํจ์๋ฅผ ํธ์ถํ์ฌ App ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํ๋ค.
๐ Provider
- Redux ์คํ ์ด๋ฅผ App ์ปดํฌ๋ํธ์ ์ ๋ฌํ๋ค.
๐ฉ๐ react-cookies
โ react cookies ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ถ๋ฌ์ค๊ธฐ
npm install react-cookies --save
โ App.js
import React from "react";
import { Component } from "react";
import CookieSave from './R085_cookieSave'
class App extends Component { //App class : ํ๋ฉด์ ๋ ๋๋ง๋ ๋ด์ฉ์ ์ ์
render() {
return (
<div>
<h1>Start React</h1>
<CookieSave/>
</div>
);
}
export default App;
โ R085_cookieSave.js
import React from "react";
import { Component } from "react";
import cookie from 'react-cookies'; //react-cookies ํจํค์ง๋ฅผ ์ํฌํธํด ์ฌ์ฉํจ
class R085_cookieSave extends Component {
componentDidMount() {
const expires = new Date() //ํ์ฌ์ ๋ ์ง์ ์๊ฐ์ ๋ถ๋ฌ์ค๋ ์๋ฐ์คํฌ๋ฆฝํธ ๋ด์ฅํจ์(new Date()) ๋ฅผ expires ๋ณ์์ ํ ๋นํจ
expires.setMinutes(expires.getMinutes() + 60) //expires.getMinute() : expires ๋ณ์์ ์๊ฐ์ ๋ถ์ผ๋ก ํ์ฐ ํจ์ ๋ฉ์๋์. 60์ ๋ํ์ผ๋ฏ๋ก ์ง๊ธ์๊ฐ์๋ค๊ฐ 60์ ๋ํด์ฃผ๋ ๊ฒ์ setMinute๋ก ๋ค์ ํ ๋นํ๋ค.
cookie.save('userid' , "React" ,{
path : '/', //path : ์ฟ ํค๊ฐ ์ ์ฅ ์๋ฒ ๊ฒฝ๋ก ํ ๋น
expires, //expires : ์ฟ ํค์ ์ ํจ์๊ฐ : 1์๊ฐ๋์ ์ฟ ํค๊ฐ ์น๋ธ๋ผ์ฐ์ ์ ๋จ๊ฒ ๋จ
// secure : true //https ๋ถ์ฌ
//httpOnly : true //document.cookie๋ก ์ฟ ํค์ ๊ทผ์ ๋ง๊ธฐ ์ํด true๊ฐ ๋ถ์ฌ
/*react-cookis์ save ํจ์์ ์ธ๊ฐ์ง ํ๋ผ๋ฏธํฐ : userid : ์ฟ ํค์ ํค, React: ์ฟ ํค๊ฐ, ์ธ๋ฒ์งธ๋ ์ฟ ํค์ต์
*/
});
}
render () {
return (
<><h3>react-cookies Save</h3></>
)
}
}
export default R085_cookieSave;
โ ๊ฒฐ๊ณผ ํ๋ฉด
๐ react-cookies load
- ์น๋ธ๋ผ์ฐ์ ์ ๋จ์์๋ ์ฟ ํค๋ฅผ key๋ก ์ ๊ทผํด value๋ฅผ ๊ฐ์ ธ์ค๋ ํจ์
โ App.js
import React from "react";
import { Component } from "react";
import CookieLoad from './R086_cookieLoad'
class App extends Component { //App class : ํ๋ฉด์ ๋ ๋๋ง๋ ๋ด์ฉ์ ์ ์
render() {
return (
<div>
<h1>Start React</h1>
<CookieLoad/>
</div>
);
}
export default App;
โ R086_cookieLoad.js
import React, {Component} from 'react';
import cookie from 'react-cookies';
class R086_cookieLoad extends Component {
componentDidMount() { //๋ ๋๋ง์ ํ๋ฉด์ ์ ์ผ ์ฒซ๋ฒ์งธ๋ก ์คํ๋๋ ์๋ช
์ฃผ๊ธฐ ํจ์
const expires = new Date()
expires.setMinutes(expires.getMinutes() + 60)
cookie.save('userid', "react200" //์ฟ ํค ์์ฑ
,{
path : '/',
expires,
//secure : true
// httpOnly : true
});
setTimeout(function() {
alert(cookie.load('userid'))
}, 1000); //1์ด ๋ค์ alert๋ฅผ ๋์ด๋ค. : ์ฟ ํค๊ฐ ์ ์ฅ๋๊ธฐ ์ํ ์ถฉ๋ถํ ์๊ฐ์
//์ด๋ cookie.load('userid')์์ userid๋ ์ฟ ํค์ key์ด๋ค.
}
render() {
return (
<><h3>react-cookies Load</h3></>
)
}
}
export default R086_cookieLoad;
๐ setTimeout (ํจ์, OO์๊ฐ)
- OO์ด ๋ค์ ํจ์๋ฅผ ์คํ์ํด
๐ cookie.load(ํค)
- ํค์ ํด๋นํ๋ ๊ฐ ์ถ๋ ฅ
โ ๊ฒฐ๊ณผ ํ๋ฉด
๐จ react-cookies remove
- ์น ๋ธ๋ผ์ฐ์ ์ ๋จ์์๋ ์ฟ ํค๋ฅผ key๋ก ์ ๊ทผํ์ฌ ์ญ์ ํ๋ ๋ฉ์๋
โ App.js
import React from "react";
import { Component } from "react";
import CookieRemove from './R087_cookieRemove'
class App extends Component { //App class : ํ๋ฉด์ ๋ ๋๋ง๋ ๋ด์ฉ์ ์ ์
render() {
return (
<div>
<h1>Start React</h1>
<CookieRemove/>
</div>
);
}
export default App;
โ R087_cookieRemove.js
import React, { Component } from "react";
import cookie from 'react-cookies';
class R087_cookieRemove extends Component{
componentDidMount() {
const expires = new Date()
expires.setMinutes(expires.getMinutes() + 60)
cookie.save('userid', "react",{
path :'/',
expires,
//secure : true,
//httpOnly : true
});
setTimeout(function() {
cookie.remove('userid', {path : '/'}); //setTimeout(function, 1000)
}, 1000);
setTimeout (function() {
alert(cookie.load('userid')) //setTimeout(function, 2000)
}, 2000);
}
render() {
return (
<><h3>react-cookies Remove</h3></>
)
}
}
export default R087_cookieRemove;
๐ cookie.remove(ํค์ด๋ฆ, {path : '์ฟ ํค ์ ์ฅ ๊ฒฝ๋ก'})
- ์ฟ ํค ์ ์ฅ๊ฒฝ๋ก์ ์ ์ฅ๋ ์ฟ ํค ์ค 'ํค์ด๋ฆ'์ ์ญ์ ํ๋ค.
โ ๊ฒฐ๊ณผ ํ๋ฉด