如何在React Native中重新渲染所有内容

Mic*_*ael 6 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}
  />
}
Run Code Online (Sandbox Code Playgroud)

即我的AppContainer this.props.styling通过mapStateToProps.包装StackNavigator得到这个通过screenProps,当商店获得新的样式数据时,强制导航器重新渲染.

我不想继续这条hacky路径.相反,我想要一个forceUpdateEverything()我可以从我的电话中调用的功能AppContainer.有这样的事吗?


编辑以评论@bennygenel的答案:

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

但是我必须将这个实现到所有组件中并通过其screenProps"hack"反应导航,如我所述.这是我希望避免的,但我想我必须走很长的路.

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

我没有让forceUpdate()工作,而不是调用它所调用的组件.我认为它不会通过所有孩子递归传播.

ben*_*nel 4

我认为执行此操作的最简单且最具性能的方法,而不是将所有样式对象保留在您的状态和 redux 中,您可以只保留某种主题标识符。这样,当您的组件使用的主题发生任何更改时,都可以应用。

\n\n

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

\n\n

来自反应文档;

\n\n
\n

默认情况下,当您的组件\xe2\x80\x99s 状态或属性更改时,您的\n 组件将重新渲染。如果你的render()方法依赖于一些\n其他数据,你可以通过调用告诉React该组件需要重新渲染\nforceUpdate()

\n\n

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

\n\n

通常你应该尽量避免所有使用forceUpdate()并且只读取 this.props 和 this.state 中的内容render()

\n
\n\n

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

\n\n

例子

\n\n
// styles.js\nconst styles = {\n  button: {\n    blue: {\n      backgroundColor: \'blue\'\n    },\n    red: {\n      backgroundColor: \'red\'\n    },\n    green: {\n      backgroundColor: \'green\'\n    }    \n  }\n};\n\nexport default styles;\n\n// Dumb component example\nimport styles from \'./styles\';\n\nconst Button = (props) => {\n  return <Button {...props} style={[props.style, styles.button[props.theme]]} />\n};\n\n// Complex component example\nimport styles from \'./styles\';\n\nexport default Button extends React.Component {\n  constructor(props) {\n    super(props);\n  }\n  render() {\n    const {style, theme} = this.props;\n    return <Button {...this.props} style={[style, styles.button[theme]]} />\n  }\n}\n\n// usage in another component\nimport React, { Component } from \'react\';\nimport { Text, View, StyleSheet } from \'react-native\';\nimport Button from \'./components/Button\'; // Custom button component\nimport styles from \'./styles\';\n\nexport default App extends React.Component {\n  constructor(props) {\n    super(props);\n  }\n  render() {\n    return(\n      <View style={styles.container}>\n        <Text style={styles.paragraph}>\n          Change code in the editor and watch it change on your phone!\n          Save to get a shareable url. You get a new url each time you save.\n        </Text>\n        <Button theme="blue" {/* other Button component props */} />\n      </View>\n    );\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

在示例中,我可以简单地传递主题名称,而不是将完整的样式对象从一个组件/屏幕传递到另一个组件/屏幕,并且themeprop 上的任何更改都将强制组件从styles常量中获取新的样式对象。

\n\n

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

\n\n

例子

\n\n
const styles = {\n  id5248698745: {\n    button: {\n      backgroundColor: \'green\'\n    },\n    label: {\n      color: \'yellow\',\n      fontSize: 18\n    },\n    paragraph: {\n      color: \'red\',\n      fontSize: 19\n    },\n    headings: {\n      color: \'wihte\',\n      fontSize: 24\n    }\n  }\n};\n\n// ...\nrender() {\n    const {style, theme} = this.props;\n    return <Button {...this.props} style={[style, styles[theme].button]} />\n}\n\n// ...\n// <Button theme={this.props.themeId} {/* other Button component props */} />\n
Run Code Online (Sandbox Code Playgroud)\n