根据屏幕上的操作,我想更新所选选项卡的图标(特别是图标上的徽章装饰器,表示"未读计数"(,而无需导航以导致重新渲染。有哪些方法可以做到这一点?
以下是使用expo init
选项卡模板进行问题的基本演示的源代码,然后进行修改以演示: https://github.com/kevgrig/rn_navigation_badge_updates
这是该回购的小吃:https://snack.expo.io/@git/github.com/kevgrig/rn_navigation_badge_updates
关键位是:
-
导航/MainTabNavigator 中的
createBottomTabNavigator
.js带有返回<TabBarIcon />
组件并传递badgeCount
参数的tabBarIcon
s。let homeTabCount = 1; HomeStack.navigationOptions = { tabBarLabel: 'Home', tabBarIcon: ({ focused }) => { return ( <TabBarIcon focused={focused} name={ Platform.OS === 'ios' ? `ios-information-circle${focused ? '' : '-outline'}` : 'md-information-circle' } badgeCount={homeTabCount} /> ); }, };
-
组件/TabBarIcon 中的
TabBarIcon
组件.js带有可选的badgeCount
参数。export default class TabBarIcon extends React.Component { render() { const { name, focused, badgeCount } = this.props; return ( <View style={badgeStyles.badgeView}> <Ionicons name={name} size={26} style={{ marginBottom: -3 }} color={focused ? Colors.tabIconSelected : Colors.tabIconDefault} /> { badgeCount > 0 && ( <View style={badgeStyles.badgeContainer}> <Text style={badgeStyles.badgeText}>{badgeCount}</Text> </View> )} </View> ); } }
屏幕 /主屏幕中主屏幕上的一个
Button
.js带有一个onPress
处理程序,我想用它来更新主屏幕选项卡的badgeCount
。export default class HomeScreen extends React.Component { onPress = () => { // TODO - how to update the badgeCount? }
我调试了可用的props.navigation
方法并看到了emit('refocus')
但这不起作用。
我用react-redux
完成了这个。大致是这样的:
import { createStore, applyMiddleware } from 'redux';
import { connect, Provider } from 'react-redux';
const defaultState = {
badgeCount: 0,
};
const ACTION_REFRESH_STATE = "ACTION_REFRESH_STATE";
function rootReducer(state = defaultState, action) {
switch (action.type) {
case ACTION_REFRESH_STATE:
const result = Object.assign({}, state);
if (action.new_state.badgeCount) {
result.badgeCount = action.new_state.badgeCount;
}
return result;
default:
return state;
}
}
function refreshState(new_state) {
return {
type: ACTION_REFRESH_STATE,
new_state: new_state,
};
}
const mapDispatchToProps = (dispatch, ownProps) => {
return {
refreshState: (new_state) => {
dispatch(refreshState(new_state));
}
}
};
const store = createStore(rootReducer);
function routeToIcon(routeName) {
if (routeName.startsWith("Home")) {
return { iconName: "md-home", mapStateToProps: state => ({ badgeCount: state.badgeCount }) };
} [...]
}
[...]
tabBarIcon: ({ focused, horizontal, tintColor }) => {
const { iconName, mapStateToProps } = routeToIcon(navigation.state.routeName);
let IconWithBadgeContainer = connect(mapStateToProps, mapDispatchToProps)(IconWithBadge);
return <IconWithBadgeContainer name={iconName} size={25} color={tintColor} />;
},
[...]
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<AppContainer
ref={navigatorRef => {
globalNavigatorRef = navigatorRef;
}}
/>
</Provider>
);
}
}