참고 사이트 : https://velog.io/@yesdoing/내맘대로-리액트-A-to-Z-1-9pjwz1o6ai
Class Component를 생성하려 하니 "react unexpected token =" Error 발생
npm install -D @babel/plugin-proposal-class-properties
npm install -D @babel/plugin-transform-runtime
npm install -D @babel/runtime
npm install -D babel-eslint
//.babelrc
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
],
"plugins": [
"@babel/plugin-proposal-class-properties",
"@babel/transform-runtime"
]
}
//.eslintrc.js
"parser": "babel-eslint",
devServer: {
contentBase: './build',
noInfo: true,
open: true,
port: PORT,
proxy: { "/api": "http://localhost:3000" }
},
Fetch API보다 Axios가 더 좋은 장점
1. 구형 브라우저 지원 가능 (Fetch API의 경우는 Polyfill이 필요)
2. 요청을 중단 시킬 수 있음
3. 응답 시간 초과 설정 방법 있음
4. CSRF 보호 기능 내장
5. JSON 데이터 자동변환
6. Node.js에서 사용 가능
7. status code 다루기 쉬움
const object1 = {
a: 'somestring',
b: 42
};
for (let [key, value] of Object.entries(object1)) {
console.log(`${key}: ${value}`);
}
Object.entries() : for..in와 같은 순서로 주어진 객체 자체의 enumerable 속성 [key,value] 쌍의 배열을 반환한다.
//TickerList.js
<TableBody>
{tickers.map(([key, ticker]) => (
<Ticker
key={key}
id={key}
min_price={ticker.min_price}
max_price={ticker.max_price}
fluctate_rate_24H={ticker.fluctate_rate_24H}
acc_trade_value_24H={ticker.acc_trade_value_24H}
/>
))}
</TableBody>
App -> Home(axios) -> TickerList(Table) -> Ticker Component(TableRow)
//Ticker.js
Ticker.defaultProps = {
min_price: '0',
max_price: '0',
fluctate_rate_24H: '0',
acc_trade_value_24H: '0',
};
Ticker.propTypes = {
id: PropTypes.string.isRequired,
min_price: PropTypes.string.isRequired,
max_price: PropTypes.string.isRequired,
fluctate_rate_24H: PropTypes.string.isRequired,
acc_trade_value_24H: PropTypes.string.isRequired,
};
//[Node Server]
//apiController.js
export const getTickers = async (req, res, next) => {
try {
const {
data: { data },
} = await axios.get('https://api.bithumb.com/public/ticker/ALL_KRW');
//throw "getTickers Error";
res.json({ data });
} catch (e) {
next(new Error(e));
}
};
export const getBalance = async (req, res, next) => {
try {
Bithumb.setApiKey(process.env.API_KEY, process.env.SECRET_KEY);
const data = await Bithumb.getMyBalance('BTC');
//throw "getBalance Error";
res.json( data[2] );
} catch (e) {
next(new Error(e));
}
};
//app.js
app.use((err, req, res, next) => {
console.error(err);
res.status(err.status || 500);
res.json({
errors: {
message: err.message,
},
});
next();
});
express에서는 모든 route에 대한 Error Handling을
오류 처리 미들웨어
로 처리한다.
//[React Client]
//Home.js
errorHandler = e => {
if (e.response) {
//요청이 이루어졌으며 서버가 2xx의 범위를 벗어나는 상태 코드로 응답
console.log(e.response);
} else if (e.request) {
//요청이 이루어졌으나 응답을 받지 못함
console.log(e.request);
} else {
//오류를 발생시킨 요청을 설정하는 중에 문제가 발생
console.log('Error', e.message);
}
console.log(e.config);
}
getTickers = async () => {
try {
const {
data: { data },
} = await axios.get('/api/ticker');
this.setState({ tickers: Object.entries(data) });
console.log(this.state.tickers);
} catch (e) {
this.errorHandler(e);
}
};
Server에서 throw로 에러 객체를 생성해서 보내면 Client에서는 해당 에러를 catch로 받은 후 해당 에러 내용(e.response)을 출력한다. 해당 axios 에러처리는 Axios 러닝 가이드를 참고하였다.
React에는 React16부터 ErrorBoundary라는 개념이 생겼다고 한다. ''ErrorBoundary''란 Component Tree의 자식 컴포넌트 트리에서 발생한 에러를 잡아내고 로그를 남기며, 나머지 컴포넌트에게 영향을 주지 않게 한다는 개념이다. 이 부분을 더 조사해보고 추후 적용해보기로 한다.
HOC란? 여러 컴포넌트의 기능 상에서 자주 반복되는 코드들을 컴포넌트로 만들어서 반복 문제를 해결하는 개념. (Don't repeat yourself) 또한 React에서 Mixin을 대체하는 데 쓰인다.
//App.js
import {createMuiTheme, ThemeProvider } from '@material-ui/core/styles';
const theme = createMuiTheme({
palette: {
primary: purple,
secondary: green,
},
background: '#eeeeee',
boxShadow: '0 2px 3px 1px gray',
});
function App() {
return (
<ThemeProvider theme={theme}>
<Home />
</ThemeProvider>
);
}
//TopChart.js
const styles = theme => ({
root: {
padding: theme.spacing(3),
//background: theme.background,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
paper: {
minWidth: 200,
padding: theme.spacing(3), //8px * 3
marginLeft: theme.spacing(1), //8px
marginRight: theme.spacing(1),
textAlign: 'center',
'&:hover': {
cursor: 'pointer',
boxShadow: theme.boxShadow,
},
},
});
...
<div className={classes.root}>
{tickers.map(([key, ticker]) => (
<Paper className={classes.paper} key={key}>
...
export default withStyles(styles)(TopChart);
이 컴포넌트에서는 withStyles Component는 styles라는 인자와 Home이라는 인자를 받아 새로운 컴포넌트를 반환한다. 컴포넌트의 props의 styles에서 정의한 스타일 정보를 적용한 클래스들을 props.classes로 가진다. classes의 root에는 스타일이 적용된 class 이름이 저장되어 있다.
Theme은 React App의 전체적인 스타일을 적용하는데 사용한다. App.js에서 createMuiTheme 메소드를 이용하여 theme을 생성하고 ThemeProvicer 컴포넌트의 theme이라는 속성에 설정한다. 이 컴포넌트에 theme 속성을 설정하면 내부의 모든 컴포넌트에서 Material-UI 컴포넌트의 스타일을 설정할때 theme을 이용할 수 있다.
TopChart 컴포넌트의 tickers가 재갱신이 되는 이유가 Home에서 혹은 TickerList에서 tickers를 재갱신하는걸로 보인다. 자세한 내용은 추후 파악해보기로 한다.