JSX 를 사용하기 위해선 늘 React 를 import 해야 했다(그것을 명시적으로 사용하지 않더라도).
JSX 코드는 babel, typescript 등을 통해 일반 javascript transpile 되었기 때문이다.
<= v16
import React from 'react';function App() { return <h1>Hello World</h1>;}// JSX -> 일반 자바스크립트function App() { return React.createElement('h1', null, 'Hello world');}
v17 버전 이후부터는 더 이상 ‘import React ~’ 구문을 직접 입력하지 않아도 된다.
v17
function App() { return <h1>Hello World</h1>;}// Inserted by a compiler (don't import it yourself!)import { jsx as _jsx } from 'react/jsx-runtime';function App() { return _jsx('h1', { children: 'Hello world' });}
# for npm usersnpm update @babel/core @babel/plugin-transform-react-jsx# for yarn usersyarn upgrade @babel/core @babel/plugin-transform-react-jsx
@babel/preset-react
# for npm usersnpm update @babel/core @babel/preset-react# for yarn usersyarn upgrade @babel/core @babel/preset-react
babel config
// If you are using @babel/preset-react{ "presets": [ ["@babel/preset-react", { "runtime": "automatic" }] ]}// If you're using @babel/plugin-transform-react-jsx{ "plugins": [ ["@babel/plugin-transform-react-jsx", { "runtime": "automatic" }] ]}
v17 버전 업한 이후에 불필요한 import 일괄삭제(선택)
react-codemod
// general reactimport React from 'react';function App() { return <h1>Hello World</h1>;}--transpile;function App() { return <h1>Hello World</h1>;}
16버전 이하에서는, 모든 컴포넌트에서 undefined를 리턴할 경우 항상 에러를 발생했다.
하지만 코딩 실수로 인해, forwardRefmemo컴포넌트 에서는 이러한 에러 처리가 누락되어 있었는데, 이제 부터 에러처리가 추가되었다.
17버전부터는 forwardRefmemo컴포넌트에서도 undefined를 리턴할 경우 에러 발생한다.
<= v16function Button() { return; // Error: Nothing was returned from render}function Button() { // We forgot to write return, so this component returns undefined. // React surfaces this as an error instead of ignoring it. <button />;}v17 +let Button = forwardRef(() => { // We forgot to write return, so this component returns undefined. // React 17 surfaces this as an error instead of ignoring it. <button />;});let Button = memo(() => { // We forgot to write return, so this component returns undefined. // React 17 surfaces this as an error instead of ignoring it. <button />;});
의도적으로 렌더링하지 않으려면 null을 반환해야한다.
Effect Cleanup Timing
useEffect 라이프 사이클 메서드의 Cleanup 타이밍을 일관되게 동작하도록 만들고 있다.
React 17 부터는 Event가 document 가 아닌 React Tree Root 로 delegate 된다.
여러 리액트 컴포넌트 수행되더라도 기본이 되는 Root Element 이벤트를 처리하기 때문에 구조/이벤트 방식이 독립적으로 수행가능하다.
리액트가 다른 기술과 사용하는 것을 더욱 용이하게 한다. 만약 외부에 jQuery가 존재하고, 내부에는 리액트가 존재한다면 이제 예상대로 이벤트 전파를 jQuery단까지 막을 수 있다.
단, DOM에 **document.addEventListener**를 활용하여 수동으로 이벤트를 붙여서 리액트의 모든 이벤트를 감지하는 코드가 존재할 수 있다. 리액트 16버전 에서는 이러한 코드가 가능했지만, 리액트 17 부터는 전파가 막히게 되므로 **document**에서도 이벤트가 발생하는지 알 수 없기때문에 capturing 방식으로 변경이 필요하다.
// <= v16document.addEventListener('click', function () { // This custom handler will no longer receive clicks // from React components that called e.stopPropagation()});// v17+document.addEventListener( 'click', function () { // Now this event handler uses the capture phase, // so it receives *all* click events below! }, { capture: true },);