我的应用程序通过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()在其调用的组件上工作。我认为它不会以递归方式传播给所有孩子。
答案 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
属性添加到根组件,并在需要时随时更改它。它会让一切都重新出现。但你会失去国家。