2018年3月30日金曜日

React16.3.0のざっくりまとめ的なお話

発表されたので自分用に簡単なまとめ。

Official Context API

公式サポートのコンテキストAPI。
今までのコンテキストAPIは16.x.x系では使えるよ的な。

// Create a theme context, defaulting to light theme
const ThemeContext = React.createContext('light');
function ThemedButton(props) {
// The ThemedButton receives the theme from context
return (
<ThemeContext.Consumer>
{theme => <Button {...props} theme={theme} />}
</ThemeContext.Consumer>
);
}
// An intermediate component
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}
class App extends React.Component {
render() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
}
view raw context0.js hosted with ❤ by GitHub

const ThemeContext = React.createContext('light');としてThemeContextを作り、ThemeContext.Providerを使うことでchildren以下に浸透させ、取り出したいところでThemeContext.Consumerとすることでcontextを取り出せる。

class Button extends React.Component {
componentDidMount() {
// ThemeContext value is this.props.theme
}
componentDidUpdate(prevProps, prevState) {
// Previous ThemeContext value is prevProps.theme
// New ThemeContext value is this.props.theme
}
render() {
const {theme, children} = this.props;
return (
<button className={theme ? 'dark' : 'light'}>
{children}
</button>
);
}
}
export default props => (
<ThemeContext.Consumer>
{theme => <Button {...props} theme={theme} />}
</ThemeContext.Consumer>
);
view raw context1.js hosted with ❤ by GitHub

Accessing Context in Lifecycle Methods
ここら辺はreduxっぽくてわかりやすいんじゃないかと。
dispatchがないバージョンみたいな感じでサクッとFlux的なことをしたいならばContext APIで十分ぽい。


createRef API

refは文字列型(ref="hogeRef")とコールバック型(ref={(ref) => {this.hogeRef = ref}})があったんだけど、推奨されてたのはコールバック型。
けどコールバック型だとcomponentDidMount時にrefを扱った処理ができなかったっていう問題点があったんだけど、それを解決するのが今回追加されるやつ。

class MyComponent extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
render() {
return <input type="text" ref={this.inputRef} />;
}
componentDidMount() {
this.inputRef.current.focus();
}
}
view raw createRef.js hosted with ❤ by GitHub

constructorの中でthis.inputRef = React.createRef();みたいな形にしてあげることで、refが生成されるので、componentDidMount時に諸々できるみたいな。
これは地味に便利。
コールバック型の中でDidMount時にしたい処理をif文付きで書かないといけなかったのをやる必要がなくなるから。


forwardRef API

HOC作ったときのrefを指定したいよね的なお話。

function withTheme(Component) {
// Note the second param "ref" provided by React.forwardRef.
// We can attach this to Component directly.
function ThemedComponent(props, ref) {
return (
<ThemeContext.Consumer>
{theme => (
<Component {...props} ref={ref} theme={theme} />
)}
</ThemeContext.Consumer>
);
}
// These next lines are not necessary,
// But they do give the component a better display name in DevTools,
// e.g. "ForwardRef(withTheme(MyComponent))"
const name = Component.displayName || Component.name;
ThemedComponent.displayName = `withTheme(${name})`;
// Tell React to pass the "ref" to ThemedComponent.
return React.forwardRef(ThemedComponent);
}
const fancyButtonRef = React.createRef();
// fancyButtonRef will now point to FancyButton
<FancyThemedButton
label="Click me!"
onClick={handleClick}
ref={fancyButtonRef}
/>;
view raw forwardRef.js hosted with ❤ by GitHub

今までだとHOC作った場合はrefを渡せなかったけど、forwardRefっていうのを使えば渡せるようになる的な。
refを直接渡そうとするとrefはpropsとして受け取れなかったから、componentRef={(ref) => {}}みたいな形で渡す必要があったんだけど、今度からこれでできるからよいみたいな。
ということはもしかしてStyled Componentみたいな形のときにもrefを渡せるようになるのかな?


Component Lifecycle Changes

ライフサイクルメソッドについて的なお話。
componentWillMount、componentWillReceiveProps、componentWillUpdateがまぁ中々厄介だったりするわけで。
とりあえずcomponentDidMountでfetchしろよとかそういう話。
一応これら3つはバージョン17まで使えるけど非推奨だよ的な。
ちなみに前に以下の記事で諸々述べてた。
https://medium.com/@baphemot/whats-new-in-react-16-3-d2c9b7b6193b
で、新しく二つ追加されたメソッドがある。

static getDerivedStateFromProps(nextProps, prevState)

class ExampleComponent extends React.Component {
// Initialize state in constructor,
// Or with a property initializer.
state = {
isScrollingDown: false,
lastRow: null,
};
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.currentRow !== prevState.lastRow) {
return {
isScrollingDown:
nextProps.currentRow > prevState.lastRow,
lastRow: nextProps.currentRow,
};
}
// Return null to indicate no change to state.
return null;
}
}

これはcomponentWillReceivePropsの代替的な。
けどstaticメソッドなのでこの中でthis.setState()は使えないわけだけどreturnした値が新しいstateになる感じ。
なのでそれらの役割も果たしたい場合にはcomponentDidUpdate(prevProps, prevState)もちゃんと使いましょう的な。
けど前にcomponentWillReceivePropsが非推奨になるよって言われてからcomponentDidUpdateで作るようにしてるんだけど全然問題ない。
別にreceivePropsでやる必要ないんじゃないかなって最近思ってるのであまり気にする必要ないんじゃないかと。


getSnapshotBeforeUpdate(prevProps, prevState)

class ScrollingList extends React.Component {
listRef = React.createRef();
getSnapshotBeforeUpdate(prevProps, prevState) {
// Are we adding new items to the list?
// Capture the current height of the list so we can adjust scroll later.
if (prevProps.list.length < this.props.list.length) {
return this.listRef.current.scrollHeight;
}
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
// If we have a snapshot value, we've just added new items.
// Adjust scroll so these new items don't push the old ones out of view.
if (snapshot !== null) {
this.listRef.current.scrollTop +=
this.listRef.current.scrollHeight - snapshot;
}
}
render() {
return (
<div ref={this.listRef}>{/* ...contents... */}</div>
);
}
}

componentDidUpdateに第三の引数が加わったよ的な。
componentDidUpdate(prevProps, prevState, snapshot)となったよ的な。
で、それはgetSnapshotBeforeUpdateでreturnした値が渡るよ的な。
なので高さだとかなんとかを返すとかそういう感じになるっぽい。
多分色々と用途があるはずなんだけどまだ思いつかない的な。


StrictMode Component

Identifying components with unsafe lifecycles -> 非推奨のライフサイクルメソッドの使用
Warning about legacy string ref API usage -> 文字列型refの使用
Detecting unexpected side effects -> ?
これらを注意してくれるらしい。


ってな感じでざっくりと変更点まとめてみた的な。
個人的にはrefとライフサイクルメソッドが中々便利になったなぁと思う。

0 件のコメント:

コメントを投稿

Pages (26)1234567 Next

Adsense