我想在所有组件中测试用户是否已连接到互联网。
我可以在每个组件中使用NetInfo
,但由于我使用redux
,我认为使用中间件(?)可以更轻松地完成。
我用过
import { createStore, applyMiddleware } from 'redux';
const netInfo = store => next => action => {
const listener = (isConnected) => {
store.dispatch({
type: types.NET_INFO_CHANGED,
isConnected,
});
};
NetInfo.isConnected.addEventListener('change', listener);
NetInfo.isConnected.fetch().then(listener);
return next(action);
};
const store = createStore(AppReducer, applyMiddleware(netInfo));
其中AppReducer
只是combineReducers(navReducer, netInfoReducer, ...)
。
它确实有效,但我真的很担心这是否表现得足够好。它似乎只运行一次,但我永远不会删除听众或任何东西。
如果您想使用isConnected
变量填充所有组件,通常会这样做吗?
答案 0 :(得分:3)
我会为此创建一个Higher-Order Component:
import React, { Component } from 'react';
import { NetInfo } from 'react-native';
function withNetInfo(WrappedComponent) {
return class extends Component {
constructor(props) {
super(props);
this.state = {};
this.handleChange = this.handleChange.bind(this);
NetInfo.isConnected.fetch().then(this.handleChange);
}
componentDidMount() {
NetInfo.isConnected.addEventListener('change', this.handleChange);
}
componentWillUnmount() {
NetInfo.isConnected. removeEventListener('change', this.handleChange);
}
handleChange(isConnected) {
this.setState({ isConnected });
}
render() {
return <WrappedComponent isConnected={this.state.isConnected} {...this.props} />;
}
}
}
export default withNetInfo;
然后你可以包装你想呈现的任何组件:
class MyComponent extends Component {
render() {
const { isConnected } = this.props;
return(
<View>
<Text>
{`Am I connected? ${isConnected}`}
</Text>
</View>
);
}
}
export default withNetInfo(MyComponent);
奖励:如果你想保留原始组件的静态方法(如果你已经定义了一些),你应该使用包hoist-non-react-statics来复制非反应特定静态:
import React, { Component } from 'react';
import { NetInfo } from 'react-native';
import hoistStatics from 'hoist-non-react-statics';
function withNetInfo(WrappedComponent) {
class ExtendedComponent extends Component {
constructor(props) {
super(props);
this.state = {};
this.handleChange = this.handleChange.bind(this);
NetInfo.isConnected.fetch().then(this.handleChange)
}
componentDidMount() {
NetInfo.isConnected.addEventListener('change', this.handleChange);
}
componentWillUnmount() {
NetInfo.isConnected. removeEventListener('change', this.handleChange);
}
handleChange(isConnected) {
this.setState({ isConnected });
}
render() {
return <WrappedComponent isConnected={this.state.isConnected} {...this.props} />;
}
}
return hoistStatics(ExtendedComponent, WrappedComponent);
}
export default withNetInfo;
答案 1 :(得分:1)
使用中间件在redux存储中保留“isConnected”不应该存在性能问题,但是您需要确保仅添加一次侦听器。我使用https://github.com/michaelcontento/redux-middleware-oneshot来实现这一目标。
答案 2 :(得分:1)
我也考虑过中间件,但也害怕如何处理sub / unsub。我决定在我的AppContainer类的componentDidMount
和componentWillUnmount
中添加和删除监听器,该类在我的MainNavigator中保存应用程序的其余部分。此类的生命周期应该遵循应用程序的生命周期,因此请确保正确地进行子/ unsub。但是,我也将使用redux操作来设置状态并在相关视图中监听它以显示“无连接”横幅。