Я хотел бы иметь возможность "постоянно" отслеживать подключение к устройству в своем адаптивном приложении.
Я уже с успехом использую redux-thunk и redux.
На самом деле я могу это сделать
import { NetInfo } from 'react-native';
import {
CONNECTION_CHECKING,
CONNECTION_AVAILABLE,
CONNECTION_UNAVAILABLE,
} from './types';
export const connectionChecking = () => {
return (dispatch) => {
dispatch ({
type: CONNECTION_CHECKING
});
NetInfo.getConnectionInfo()
.then((connectionInfo) => {
console.log('Connection info: ', connectionInfo);
switch (connectionInfo.type) {
case 'cellular':
dispatch ({
type: CONNECTION_AVAILABLE,
payload: connectionInfo.type
});
break;
case 'wifi':
dispatch ({
type: CONNECTION_AVAILABLE,
payload: connectionInfo.type
});
break;
default:
dispatch ({
type: CONNECTION_UNAVAILABLE,
});
}
})
.catch((error) => console.warn(error));
};
};
Но я не знаю, как отправлять новые действия при изменении соединения.
Из ответного документа я вижу следующее:
NetInfo.addEventListener(
'connectionChange',
handleConnectivityChange
);
Но... как отправить действие внутри прослушивателя событий?
Я попытался добавить это в тот же файл действия
NetInfo.addEventListener(
'connectionChange', (connectionInfo) => {
return (dispatch) => {
console.log('Connection info changed ', connectionInfo);
switch (connectionInfo.type) {
case 'cellular':
case 'wifi':
dispatch ({
type: CONNECTION_AVAILABLE,
payload: connectionInfo.type
});
break;
default:
dispatch ({
type: CONNECTION_UNAVAILABLE,
});
}
};
}
);
У меня нет никаких результатов, нет console.log, и поэтому я думаю, что это неправильный путь
Вам просто нужно настроить прослушиватель событий где-нибудь с доступом к функции dispatch
.
Проще всего сделать (разрешая чистую отмену подписки) - установить их в свой самый верхний подключенный компонент:
class MyApp extends Component {
constructor(props) {
super(props);
// Dispatch an action from your event handler (and do whatever else)
this._handleConnectionChange = (connectionInfo) => props.dispatch({
type: 'CONNECTION_CHANGE',
connectionInfo
});
NetInfo.addEventListener('connectionChange', this._handleConnectionChange);
}
componentWillUnmount() {
NetInfo.removeEventListener('connectionChange', this._handleConnectionChange);
}
}
export default connect()(MyApp); // MyApp must be connected
Лично мне нравится обертывать подобные вещи в thunk, чтобы избежать обработки слушателем загромождения моих компонентов. Важным моментом здесь является то, что штыри, такие как связанные компоненты, имеют доступ к dispatch
, поэтому, определяя слушателя во внутренней части thunk, мы можем отправлять действия (или больше thunks) в ответ на изменения.
// connectionActions.js
let handleConnectionChange;
export function registerListeners() {
return (dispatch) => {
handleConnectionChange = (connectionInfo) => {
dispatch(connectionChanged(connectionInfo));
}
NetInfo.addEventListener('connectionChange', handleConnectionChange);
}
}
export function unregisterListeners() {
return (dispatch) => {
handleConnectionChange && NetInfo.removeEventListener('connectionChange', handleConnectionChange);
}
}
function connectionChanged(connectionInfo) {
return (dispatch) => {
switch (connectionInfo.type) {
case 'cellular':
dispatch({
type: CONNECTION_AVAILABLE,
payload: connectionInfo.type
});
break;
// ...Other cases
}
}
}
И тогда вы можете отправлять registerListeners()
и unregisterListeners()
из MyApp
а не определять подробности слушателей там:
// app.js
// ...other imports
import * as connectionActions from './connectionActions'
class MyApp extends Component {
constructor(props) {
super(props);
// Dispatch your thunk to take care of the registration
props.dispatch(connectionActions.registerListeners());
}
componentWillUnmount() {
this.props.dispatch(connectionActions.unregisterListeners());
}
}
export default connect()(MyApp)
В приложениях, где у меня есть несколько возможных компонентов верхнего уровня (например, разные варианты сборки с разными домашними страницами или экран входа в систему, который не является частью основного навигатора), мне нравится использовать этот шаблон и обернуть его в компонент более высокого порядка:
// hoc/withNetListeners.js
export default function withNetListeners(SourceComponent): {
class HOC extends React.Component {
constructor(props) {
super(props);
props.dispatch(connectionActions.registerListeners());
}
componentWillUnmount() {
this.props.dispatch(connectionActions.unregisterListeners());
}
render() {
return <SourceComponent {...this.props} />;
}
}
return hoistStatics(HOC, SourceComponent); // Package hoist-non-react-statics
}
И затем в зависимости от того, какой компонент действуют как ваш корень (ы):
// app.js
class MyApp extends Component {
// ... Just your UI, no listeners ...
}
// Inject the listeners with a HOC. Make you 'connect' last, because
// 'withNetListeners' needs to be given access to 'dispatch'.
export default connect()(withNetListeners(MyApp))
NetInfo.addEventListener
!NetInfo.addEventListener
может быть яснее ..)