LoginSignup
3
2

More than 3 years have passed since last update.

React Nativeで、react-navigationとunstatedを同居させるTips

Posted at

課題

 React Nativeにおいて、react-navigationとunstatedはどちらも有用で使いたいが、unstatedをconstructor()内や、componentDidMount()内などで使いたくてコンポーネントをHOC化すると、react-navigationが使えなくなる。

ダメなコード1

 react-navigationは準備済みだとして、以下の普通のコードだと、constructor()内では、unstatedで作ったグローバルStateがよめない。

HomeScreen.js
import React from "react";
import { Button, Text, View } from "react-native";
import { Subscribe } from "unstated";

import GlobalStateContainer from "../containers/GlobalStateContainer";

export default class HomeScreen extends React.Component {
  constructor(props) {
    super(props);
    this.state = { item: globalState.state.item };  // ← [ダメ]グローバルState内のデータをローカルStateにコピーして使いたいのに、できない
  }

  render() {
    return (
      <Subscribe to={[GlobalStateContainer]}>
        {globalState =>
          <View>
            <Text>Hello World! {globalState.state.item}</Text>        // ← これはOK
            <Button title="Go to InvoiceEdit" onPress={() => this.props.navigation.navigate("InvoiceEdit")} />
          </View>
        }
      </Subscribe>
    );
  }
}

ダメなコード2

 HOC化する。navigationがつかえなくなる。

HomeScreen.js
import React from "react";
import { Button, Text, View } from "react-native";
import { Subscribe } from "unstated";

import GlobalStateContainer from "../containers/GlobalStateContainer";

class HomeScreenContent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { item: props.globalState.state.item };  // ← これはOK
  }

  render() {
    let globalState = this.props.globalState;
    return (
      <View>
        <Text>Hello World! {globalState.state.item}</Text> // ← これはOK
        <Text>Hello World! {this.state.item}</Text>        // ← これはOK
        <Button title="Go to InvoiceEdit" onPress={() => this.props.navigation.navigate("InvoiceEdit")} />  // ← ここでコケる
      </View>
    );
  }
}

const HomeScreen = () => {
  return (
    <Subscribe to={[GlobalStateContainer]}>
      {globalState => <HomeScreenContent globalState={globalState} />}
    </Subscribe>
  );
};

export default HomeScreen;

 HOC化したことで、HomeScreenContentのthis.propsにnavigationが入ってこないため、this.props.navigation.navigate()でコケるのです。原因は、以下の部分でSubscribeからHomeScreenContentに向けて、自動的にはpropsが引き継がれないために、navigationもHomeScreenContentに届けられないためです。

打開策

 以下ならうまく動く。

HomeScreen.js
import React from "react";
import { Button, Text, View } from "react-native";
import { Subscribe } from "unstated";

import GlobalStateContainer from "../containers/GlobalStateContainer";

class HomeScreenContent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { item: props.globalState.state.item };  // ← これはOK
  }

  render() {
    return (
      <View style={styles.container}>
        <Text>Hello World! {globalState.state.item}</Text> // ← これはOK
        <Text>Hello World! {this.state.item}</Text>        // ← これはOK
        <Button title="Go to InvoiceEdit" onPress={() => this.props.navigation.navigate("InvoiceEdit")} />  // ← これもOK
      </View>
    );
  }
}

const HomeScreen = ({ navigation }) => {
  return (
    <Subscribe to={[GlobalStateContainer]}>
      {globalState => <HomeScreenContent globalState={globalState} navigation={navigation} />}
    </Subscribe>
  );
};

export default HomeScreen;

 ポイントは、navigationを名指しで子供に伝搬してやったことです。通常のpropsもこのように伝搬させなくてはいけません。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2