メインコンテンツにスキップ

直接操作

サブツリー全体の再レンダリングをトリガーするためにstate/propsを使用せずに、コンポーネントを直接変更する必要がある場合があります。たとえば、ブラウザでReactを使用する場合、DOMノードを直接変更する必要がある場合があり、モバイルアプリのビューについても同じことが言えます。setNativePropsは、DOMノードにプロパティを直接設定することに相当するReact Nativeです。

注意

頻繁な再レンダリングがパフォーマンスのボトルネックになる場合は、setNativePropsを使用してください!

直接操作は、頻繁に使用するツールではありません。通常は、コンポーネント階層のレンダリングと多数のビューの調整のオーバーヘッドを回避するために、連続的なアニメーションを作成する場合にのみ使用します。setNativePropsは命令型であり、状態をReactコンポーネント内ではなくネイティブレイヤー(DOM、UIViewなど)に保存するため、コードの推論がより困難になります。

使用する前に、setStateshouldComponentUpdateで問題を解決してみてください。

TouchableOpacityでのsetNativeProps

TouchableOpacityは、子コンポーネントの不透明度を更新するために内部的にsetNativePropsを使用します。

const viewRef = useRef<View>();
const setOpacityTo = useCallback(value => {
// Redacted: animation related code
viewRef.current.setNativeProps({
opacity: value,
});
}, []);

これにより、次のコードを記述でき、子はその事実を知ったり、実装を変更したりすることなく、タップに応じて不透明度が更新されることを知っています。

<TouchableOpacity onPress={handlePress}>
<View>
<Text>Press me!</Text>
</View>
</TouchableOpacity>

setNativePropsが利用できないと仮定しましょう。その制約で実装する1つの方法は、不透明度の値を状態に保存し、onPressがトリガーされるたびにその値を更新することです。

const [buttonOpacity, setButtonOpacity] = useState(1);
return (
<TouchableOpacity
onPressIn={() => setButtonOpacity(0.5)}
onPressOut={() => setButtonOpacity(1)}>
<View style={{opacity: buttonOpacity}}>
<Text>Press me!</Text>
</View>
</TouchableOpacity>
);

これは、元の例と比較して計算負荷が高くなります。Reactは、ビューとその子の他のプロパティが変更されていない場合でも、不透明度が変更されるたびにコンポーネント階層を再レンダリングする必要があります。通常、このオーバーヘッドは問題になりませんが、連続的なアニメーションを実行したり、ジェスチャーに応答したりする場合、コンポーネントを慎重に最適化することで、アニメーションの忠実度を向上させることができます。

NativeMethodsMixinでのsetNativePropsの実装を見ると、RCTUIManager.updateViewのラッパーであることがわかります。これは、再レンダリングの結果として生じるまったく同じ関数呼び出しです。 - ReactNativeBaseComponentのreceiveComponentを参照してください。

複合コンポーネントとsetNativeProps

複合コンポーネントはネイティブビューによってバックアップされていないため、それらに対してsetNativePropsを呼び出すことはできません。この例を考えてみましょう

これを実行すると、すぐにこのエラーが表示されます:Touchable child must either be native or forward setNativeProps to a native component。これは、MyButtonが、不透明度を設定する必要があるネイティブビューによって直接バックアップされていないために発生します。次のように考えることができます。createReactClassでコンポーネントを定義した場合、それにstyle propを設定してそれが機能することを期待しないでしょう。ネイティブコンポーネントをラップしていない限り、style propを子に渡す必要があります。同様に、ネイティブにバックアップされた子コンポーネントにsetNativePropsを転送します。

子へのsetNativePropsの転送

setNativePropsメソッドはViewコンポーネントへの参照に存在するため、カスタムコンポーネントの参照をレンダリングする<View />コンポーネントの1つに転送するだけで十分です。これは、カスタムコンポーネントでsetNativePropsを呼び出すと、ラップされたViewコンポーネント自体でsetNativePropsを呼び出した場合と同じ効果があることを意味します。

これで、TouchableOpacity内でMyButtonを使用できるようになりました!

{...props}を使用して、すべての子ビューにpropsを渡していることに気づいたかもしれません。これは、TouchableOpacityが実際には複合コンポーネントであるためであり、子でsetNativePropsに依存することに加えて、子がタッチ処理を実行する必要があるためです。これを行うために、TouchableOpacityコンポーネントにコールバックするさまざまなpropsを渡します。対照的に、TouchableHighlightはネイティブビューによってバックアップされており、setNativePropsを実装することのみが必要です。

TextInput値を編集するためのsetNativeProps

setNativePropsのもう1つの非常に一般的なユースケースは、TextInputの値を編集することです。bufferDelayが低く、ユーザーが非常に速く入力すると、TextInputのcontrolledプロパティが文字をドロップすることがあります。一部の開発者は、このプロパティを完全にスキップし、代わりに必要に応じてsetNativePropsを使用してTextInput値を直接操作することを好みます。たとえば、次のコードは、ボタンをタップしたときに入力を編集する方法を示しています

clearメソッドを使用してTextInputをクリアし、同じアプローチを使用して現在の入力テキストをクリアできます。

render関数との競合の回避

render関数によっても管理されているプロパティを更新すると、コンポーネントが再レンダリングされ、そのプロパティが変更されるたびに、setNativePropsから以前に設定された値は完全に無視され、上書きされるため、予期しない混乱を招くバグが発生する可能性があります。

setNativeProps & shouldComponentUpdate

shouldComponentUpdateをインテリジェントに適用することで、変更されていないコンポーネントサブツリーの調整に関わる不必要なオーバーヘッドを回避できます。これにより、setNativePropsの代わりにsetStateを使用するのに十分なパフォーマンスが得られる場合があります。

その他のネイティブメソッド

ここで説明するメソッドは、React Nativeが提供するデフォルトコンポーネントのほとんどで使用できます。ただし、それらはネイティブビューによって直接バックアップされていない複合コンポーネントでは利用できないことに注意してください。これには通常、自分のアプリで定義するほとんどのコンポーネントが含まれます。

measure(callback)

指定されたビューの画面上の位置、幅、高さをビューポートで判断し、非同期コールバックを介して値を返します。成功した場合、コールバックは次の引数で呼び出されます

  • x
  • y
  • 高さ
  • pageX
  • pageY

これらの測定値は、ネイティブでレンダリングが完了するまで利用できないことに注意してください。測定値をできるだけ早く必要とし、pageXpageYが必要ない場合は、代わりにonLayoutプロパティを使用することを検討してください。

また、measure()によって返される幅と高さは、ビューポート内のコンポーネントの幅と高さです。コンポーネントの実際のサイズが必要な場合は、代わりにonLayoutプロパティを使用することを検討してください。

measureInWindow(callback)

指定されたビューのウィンドウ内の位置を判断し、非同期コールバックを介して値を返します。Reactルートビューが別のネイティブビューに埋め込まれている場合、これは絶対座標を与えます。成功した場合、コールバックは次の引数で呼び出されます

  • x
  • y
  • 高さ

measureLayout(relativeToNativeComponentRef, onSuccess, onFail)

measure()と同様ですが、relativeToNativeComponentRef参照で指定された祖先を基準にしてビューを測定します。これは、返される座標が祖先ビューの原点xyを基準にしていることを意味します。

このメソッドは、relativeToNativeNodeハンドラー(参照の代わりに)でも呼び出すことができますが、このバリアントは非推奨です。

focus()

指定された入力またはビューのフォーカスを要求します。トリガーされる正確な動作は、プラットフォームとビューのタイプによって異なります。

blur()

入力またはビューからフォーカスを削除します。これはfocus()の反対です。