在 React Native 中有条件地渲染不同的组件是否有更好或更优雅的方式?

Is there a better or more elegant way to conditionally render different components in React Native?

我是 React Native 的新手,我正在尝试创建一个带有自定义导航栏的应用程序,当您单击链接时它会在页面之间跳转。

这是我的代码的简化版本:

class App extends Component {

  constructor(props) {
    super(props);
    this.state = {
      dicePage: true,
      itemsPage: false
    }
  }

  dicePress = () => {
        this.setState({
          dicePage: true,
          itemsPage: false
        })
  }
  itemsPress = () => {
        this.setState({
          dicePage: false,
          itemsPage: true
        })
  }

  render() {
    return (
      <View style={styles.container}>
        <ImageBackground source={backgroundTile} style={styles.bgImage}>
          <View style={styles.content}>
            <View style={styles.logoContainer}>
              <Image source={require('./assets/images/Logo.png')} style={styles.logo} />
            </View>
            {this.state.dicePage && <DicePage />}
            {this.state.itemsPage && <ItemsPage />}
            
            
            <NavBar value='Dice' dicePress={this.dicePress} itemsPress={this.itemsPress} />
          </View>
        </ImageBackground>
      </View>    
    );
  }
}

export default App;

class NavBar extends Component {
    constructor(props) {
        super(props);
    }
    render() {
        return (
            <View style={styles.bottomNav}>
                <TouchableOpacity onPress={this.props.dicePress}>
                    <Text key='dice' style={styles.nav}>Dice</Text>
                </TouchableOpacity>
                <TouchableOpacity onPress={this.props.itemsPress}>
                    <Text key='items' style={styles.nav}>Items</Text>
                </TouchableOpacity>
            </View>
        )
    }
}

export default NavBar;

所以这在我测试应用程序时有效 - 我将有 4 或 5 页,所以需要比三元运算符等更多的选项 - 但我认为可能有更好或更优雅的方法这个。

我已经尝试过 React Navigator 和其他东西,但我真的在寻找实现这一目标的绝对最简单的方法(希望使用 DRY 编码,因为重复对我来说是错误的)。我应该为此映射链接 函数吗?我不认为我以前映射过函数并意识到可能应该有一个适用于所有人的适应性函数。

感谢任何建议!

第一种方法

您可以创建一个 pages 对象,其中每个键都是页面的标识符,每个对应的值是代表页面的组件:

const pages = {
  dicePage: DicePage,
  itemsPage: ItemsPage
};

这样我们就可以只根据键来决定应该呈现什么,并且所有导航链接都可以共享同一个 onPress 处理程序。

App.js

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      currentPage: "dicePage" // Default page
    };
  }

  pagePress = (pageName) => {
    this.setState({ currentPage: pageName });
  };

  render() {
    const Page = pages[this.state.currentPage]; // What page should be rendered (based on the `currentPage` key)
    return (
      <View>
        <View>
          <Page />
          <NavBar value="Dice" pagePress={this.pagePress} />
        </View>
      </View>
    );
  }
}

Navbar.js

class NavBar extends Component {
  render() {
    return (
      <View>
        <TouchableOpacity onPress={() => this.props.pagePress("dicePage")}>
          <Text key="dice">Dice</Text>
        </TouchableOpacity>
        <TouchableOpacity onPress={() => this.props.pagePress("itemsPage")}>
          <Text key="items">Items</Text>
        </TouchableOpacity>
      </View>
    );
  }
}

因此,如果您想用更多页面扩展它,您只需将键值对添加到 pages 对象并链接到您的 Navbar.

我删除了样式和图像等一些内容以简化示例。

第二种方法

const pages = [
  { key: "dicePage", page: DicePage, pageLinkName: "Dice" },
  { key: "itemsPage", page: ItemsPage, pageLinkName: "Items" },
];

class NavBar extends Component {
  render() {
    return (
      <View>
        {pages.map((page) => {
          return (
            <TouchableOpacity
              onPress={() => this.props.pagePress(page.key)}
              key={page.key}
            >
              <Text>{page.pageLinkName}</Text>
            </TouchableOpacity>
          );
        })}
      </View>
    );
  }
}

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      currentPage: "dicePage", // Default page
    };
  }

  pagePress = (pageName) => {
    this.setState({ currentPage: pageName });
  };

  render() {
    const Page = pages.filter((page) => page.key === this.state.currentPage)[0]
      .page;
    return (
      <View>
        <View>
          <Page />
          <NavBar value="Dice" pagePress={this.pagePress} />
        </View>
      </View>
    );
  }
}

大致相同的方法,但是 pages 的结构发生了变化,您现在也不需要手动添加新链接,而只需要向 pages 添加新对象,这现在是一个数组。