react16 주요기능

2018-12-04

##react 16의 주요기능에 대해서 알아보자

1.return값

기존의 react는 항상 return할 때마다 span태그나 배열로 감싸야했다.

1
2
3
4
5
6
7
8
render() {
return (
<span>
<Header/>
<Footer/>
</span>
)
}

react16에서는 Fragment라는 것을 지원한다.
또한 <>로도 대체 가능하다.

1
2
3
4
5
6
7
8
9
10
11
12
import React, { Component, Fragment } from 'react';

class Example extends Component {
render() {
return (
<Fragment>
<Header/>
<Footer/>
</Fragment>
);
}
}

return 할때 string으로도 가능하다.

1
2
3
render() {
return "string"
}

2.Portals

기존에는 리액트의 루트 밖에서 변경할 수 없었다.
그러나 createPortal은 리액트 루트 밖에서 렌더할 때 사용할 수 있다.
주로 iframe이나 html을 변경하지 못하거나 리액트 플러그인을 만들 때 사용한다.

index.html파일

1
2
<div id="root"></div>
<div id="portal"></div>

id가 root인 애는 리액트 루트이며 portal 리액트 루트 밖에서 이용할 것이다.

app.js파일

1
2
3
4
ReactDOM.render(
<Main/>,
document.getElementById("root")
);

Main파일

1
2
3
4
5
6
7
8
9
10
11
import React, { Component, Fragment } from 'react';
import { createPortal } from 'react-dom';

const Message = () => return "mess"
class Main extends Component {
render() {
return (
createPortal(<Message/>, document.getElementById('portal'))
)
}
}

이렇게 하면 실제로 portal이라는 아이디 값에 Message라는 컴포넌트가 매핑된다.

3.Error Boundaries

부모에서 child의 에러를 잡을 수 있다.
이를 통해 에러를 구분하고 대처할 수 있다.
componentDidCatch를 사용해서 에러를 잡을 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class ErrorMaker extends  Component {
state = {
friends: ['ju', 'young']
}

componentDidMount = () => {
setTimeout(() => {
this.setState({
friends: null,
})
}, 2000)
}

render() {
const { friends } = this.state;
return friends.map(friend => `${friend}`)
}
}

const ErrorfallBack = () => "Sorry";

class ExamplePortal extends Component {
state = { hasError: false};

componentDidCatch = (error, info) => {
this.setState({
hasError: true,
});
console.log(`catched ${error} info: ${JSON.stringify(info)}`)
}

render() {
return {hasError ? <ErrorfallBack/> : <ErrorMaker/>}
}
}

ExamplePortal 이라는 부모 컴포넌트에서 처음엔 ErrorMaker를 보여주다가 2초가 지난 후에
에러가 발생하면 ErrorfallBack 컴포넌틀르 보여준다.
에러에 대한 처리를 이런식으로 하면 코드가 난잡해지며 보기 좋지 않다.
그래서 나온게 HOC이다…??? –>hoc정확하게 다시 알아보기!!(강의 돌려보기)

4. HOC(higher-order component)

HOC는 컴포넌트를 보호한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
const BoundaryHOC = ProtectedComponent =>
class Boundary extends Component {
state = {
hasError: false,
};

componentDidCatch = () => {
this.setState({
hasError: true,
})
}

render () {
const { hasError } = this.state;
if (hasError) {
return <ErrorfallBack/>
} else {
return <ProtectedComponent/>
}
}
}

const PErrorMaker = BoundaryHOC(ErrorMaker) //컴포넌트 보호

class ExamplePortal extends Component {
render() {
return (
<Fragment>
<PErrorMaker/>
</Fragment>
);
}
}
export default BoundaryHOC(ExamplePortal); //클래스도 보호 가능

5. createRef, forwardRef

기존에 ref는 자식요소에 접근할 때 이용하곤 했다.
React 16.3부터는 createRef 를 사용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import React, { Component } from 'react';
import Test from './Test';

class App extends Component {
constructor() {
super();
this.app = React.createRef();
}

componentDidMount() {
if (this.app) {
this.app.current.handleRef();
}
}

render() {
return (
<div>
<Test ref={this.app}/>
</div>
);
}
}

export default App;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import React, { Component } from 'react';

class Test extends Component {
constructor() {
super();
this.div = React.createRef();
}

handleRef = () => {
if (this.div) {
console.log("hi")
}
}

render() {
return (
<div ref={this.div}>
test
</div>
);
}
}

export default Test;

부모요소가 app이고 test가 자식요소이다. app.js에서 didmount에서 자식요소의 함수에 접근을 하면 콘솔창에
‘hi’가 찍히는 것을 볼 수 있다.
그런데 만약 HOC로 test컴포넌트로 보호되어 있으면 어떻게 될까?
이때는 forwardRef를 사용해야 한다. createRef는 HOC로 만들어진 컴포넌트의 속성에 ref가 있으면 리턴되는
컴포넌트의 ref를 가져오기 못한다. forwardRef는 이러한 문제를 해결하기 위해서 HOC내부에서 사용하면 리턴되는
컴포넌트에 전달할 수 있다.

Test.js파일에서 withHOC라는 HOC로 컴포넌트가 보호되어있다는 가정하(export default withHOC(Test))에 실행해보면 된다.
마찬가지로 ‘hi’가 나오는 것을 볼 수 있다.

1
2
3
4
5
import React from 'react';            
const withHOC = Component => React.forwardRef((props, ref) => {
return <Component {...props} ref={ref} />
});
export default withHOC;