如何在React Native

时间:2017-10-10 06:30:00

标签: reactjs react-native redux

我的应用程序通过REST API提供主题(颜色和样式)。每当在服务器上更改主题时,应用程序都会通过套接字通信获得通知,以便它可以通过REST获取新主题。

主题是在Redux Saga中获取的,颜色被保存到Redux商店(以便能够持久保存到磁盘)以及我可以从任何地方到达的“全局”单例对象,即使是非连接组件。

当新主题到来时,我想重新渲染应用中的每个元素。我设法以一种hacky方式重新渲染所有连接商店的组件 - 通过注入一个虚拟属性,当新主题发生变化时,该属性会发生变化。

有没有办法forceUpdate整个应用程序?

问题领域:

  • 哑组件(不知道主题变化)

  • 非常聪明的组件(知道商店,但知道不会徒劳地重新渲染)

这是一个hacky force-re-render of react-navigation的例子:

myAppContainer.render() {

  <AppRouter
    screenProps={this.props.styling}
  />
}

即。我的AppContainer通过this.props.styling获取mapStateToProps。包裹的StackNavigator通过screenProps获取此内容,强制导航器在商店获取新的样式数据时重新呈现。

我不想继续这条骇人的道路。相反,我想要一个forceUpdateEverything()函数,我可以从AppContainer调用它。有这样的事吗?

编辑以评论@bennygenel的答案:

我认为Benny所描述的基本上就是我所做的。 this.props.styling中的更改会触发重新渲染。

但我必须在所有组件中实现这一点,并通过其screenProps“hack”反应导航,如我所述。这是我希望避免的,但我想我必须走很长的路。

我正在使用immutable.js,所以发送完整的样式而不仅仅是主题名称没什么大不了的,因为它只是一个指针,可以快速地与之前的值进行比较以寻找变化。

我没有让forceUpdate()在其调用的组件上工作。我认为它不会以递归方式传播给所有孩子。

2 个答案:

答案 0 :(得分:3)

我认为这样做最简单,最具性能的方式,而不是将所有样式对象保存在你的状态和redux中,你可以只持有某种主题标识符。这种方式可以应用组件使用的主题发生任何更改。

在反应中有一种叫做forceUpdate的方法。虽然这听起来像你正在寻找的东西,但使用它并不是一个很好的做法。

来自反应文档;

  

默认情况下,当您的组件的状态或道具发生变化时,您的   组件将重新渲染。如果您的render()方法取决于某些方法   其他数据,你可以告诉React组件需要重新渲染   致电forceUpdate()

     

调用forceUpdate()将导致调用render()   组件,跳过shouldComponentUpdate()。这将触发   子组件的正常生命周期方法,包括   每个孩子的shouldComponentUpdate()方法。 React仍然只会   如果标记发生更改,则更新DOM。

     

通常情况下,您应该尽量避免使用forceUpdate(),并且只能在render()中读取this.props和this.state。

我认为您应该在应用中创建主题逻辑并相应地更改主题。

示例

// styles.js
const styles = {
  button: {
    blue: {
      backgroundColor: 'blue'
    },
    red: {
      backgroundColor: 'red'
    },
    green: {
      backgroundColor: 'green'
    }    
  }
};

export default styles;

// Dumb component example
import styles from './styles';

const Button = (props) => {
  return <Button {...props} style={[props.style, styles.button[props.theme]]} />
};

// Complex component example
import styles from './styles';

export default Button extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    const {style, theme} = this.props;
    return <Button {...this.props} style={[style, styles.button[theme]]} />
  }
}

// usage in another component
import React, { Component } from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Button from './components/Button'; // Custom button component
import styles from './styles';

export default App extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return(
      <View style={styles.container}>
        <Text style={styles.paragraph}>
          Change code in the editor and watch it change on your phone!
          Save to get a shareable url. You get a new url each time you save.
        </Text>
        <Button theme="blue" {/* other Button component props */} />
      </View>
    );
  }
}

在我的例子中,我使用定义为硬编码对象的样式。您可以向其添加API调用和套接字通信逻辑。

在示例中,不是将完整样式对象从一个组件/屏幕传递到另一个组件/屏幕,我只需简单地传递主题名称,theme prop上的任何更改都将强制组件从{{1}获取新样式对象常数。

不需要为每个对象设置主题。您可以在对象中使用更高的属性。

示例

styles

答案 1 :(得分:0)

最脏的方法:将key属性添加到根组件,并在需要时随时更改它。它会让一切都重新出现。但你会失去国家。