React.js, assign to arguments
useState
のような状態を扱う自作hookを作る際、引数に関数を使うことがあります。
Reactのpropsなど、引数代入することで型を特定できたり、コードが縮小できて便利です。
たとえば、useStateでは初期値の計算が重かったり前の値を扱痛い場合、引数に関数を指定させます。
const [rows, setRows] = useState(() => createRows(props.count));
このuseStateのソースコードをみると、引数の型は(()=>S)|S
として、初めに引数自体に関数の結果を代入していました。
function mountState<S>(
initialState: (() => S) | S,
): [S, Dispatch<BasicStateAction<S>>] {
const hook = mountWorkInProgressHook();
if (typeof initialState === 'function')
initialState = initialState(); // 引数にも代入できる!
/*...*/
}
Reactのchildrenに便利
props.childrenでは子要素が二つ以上のときだけ配列になります。
なので子要素がなかったり一つだったりするときは配列ではないので、
children.length
やchildren.map
にエラーが出ます。
次のように、 children
を先に配列に直すと予期しないエラーを減らすことができたりできます。
import React, {Children} from 'react';
const App = ({children}) => {
children = Children.toArray(children)
return children.filter(Boolean) // エラー出ない!
}
再帰化させるのに便利
孫要素に自身のコンポーネントを付与することで、自作した機能を子要素すべてに作用させることができます。 次のようにchildrenを変更すれば、孫要素が複数のときだけ再帰的に機能を与えられます。 (以下の例では、Redsで囲んだすべての子要素が赤くなります。)
import React, {Children, cloneElement} from 'react'
const Reds = ({children}) => {
children = Children.map( children, (child, key) => {
const grand = Children.toArray( child.props.children ) || []
return grand.length > 1
? cloneElement(child, {children:grand[0], grand:
<Reds> {grand.slice(0)} </Reds>
})
: child
}
const style = {background:"red"}
return <div {...{style, children}} />
}}