【问题标题】:React Native: How do I send a value from a promise returned by taskmanager to a redux store?React Native:如何将 taskmanager 返回的 promise 中的值发送到 redux 商店?
【发布时间】:2020-09-22 21:28:19
【问题描述】:

我正在尝试在 react native expo 中从 taskmanager 向 redux 存储发送一个值。我不确定我哪里出错了,以及如何正确提取值并将其发送到我的 redux 商店。就我而言,我试图从 expo 的 taskmanager geofence api 访问 state 值,其中状态 1 表示您已进入,状态 2 表示您已退出:

You've entered region: Object {
  "identifier": "court",
  "latitude": 40.7634642,
  "longitude": -73.9290698,
  "radius": 20,
  "state": 1,
}

如何更改我的任务管理器脚本以访问此值?

TaskManager.defineTask(TASK_CHECK_GEOFENCE, ({ data: { eventType, region }, error }) => {
  if (error) {
    // check `error.message` for more details.
    return;
  }
  if (eventType === Location.GeofencingEventType.Enter) {
    console.log("You've entered region:", region);
    //this.props.setEnterRegion({ inRegion: region.identifier })
     ****** HERE IS WHERE I WOULD LIKE TO SEND THE VALUE TO MY STORE
  } else if (eventType === Location.GeofencingEventType.Exit) {
    console.log("You've left region:", region);
     ****** HERE IS WHERE I WOULD LIKE TO SEND THE VALUE TO MY STORE
  }
});

下面是我的其他代码供参考:

Home.js

//links for support


//https://stackoverflow.com/questions/60199774/expo-location-geofencing-not-working-on-standalone-devices-ios
//https://docs.expo.io/versions/latest/sdk/task-manager/
//https://www.youtube.com/watch?v=2NUUN0dX4kE
//https://stackoverflow.com/questions/59133892/expo-startgeofencingasync-not-starting



import { StyleSheet, Text, View, Button } from 'react-native';
import React, { Component } from 'react';
import * as Permissions from 'expo-permissions';
import * as Location from 'expo-location';
import * as TaskManager from 'expo-task-manager';
import { connect } from "react-redux";


class Home extends Component {

state= {
  inRegion:null,
  hasLocationPermission: null,
  myLocation: {
    //latitude: 40.6,
    //longitude: -73.5
    latitude: 40.7634642,
    longitude: -73.9290698
  }
}

componentDidMount() {
  this.getLocationsPermissions();
  this.startBackgroundUpdate();
  this.startGeofence();

}


//ask for location permissions 
getLocationsPermissions = async () => {
  let { status } = await Permissions.askAsync(Permissions.LOCATION);
  //status && console.log('location: ', status)
  if (status !== 'granted') {
    this.setState({
      errorMessage: 'Permission to access location was denied',
    });
    } else {
      this.setState({ hasLocationPermission : status })
    }
}

//define and start geofence
startGeofence = async () => {
  console.log('starting geofencing test ...')
  let x = Location.startGeofencingAsync('TASK_CHECK_GEOFENCE',
    [
    {
      identifier: 'court',
      latitude: this.state.myLocation.latitude,
      longitude: this.state.myLocation.longitude,
      radius: 20,
      notifyOnEnter: true,
      notifyOnExit: true,
     }
     ]
    )//.then((res) => res.json()).then((res) => {console.log(res)})
    this.sendTask(x)
    //this.props.setEnterRegion(inRegion);
  
};

//start tracking in background
startBackgroundUpdate = () => {
  Location.startLocationUpdatesAsync(TASK_FETCH_LOCATION, { accuracy: Location.Accuracy.Highest })
}

//send to store from task
sendTask = (x) => {
  console.log('entered region...', x)
  
  //this.props.setEnterRegion(x)
  //this.setState({inRegion : x})
  
}


  render() {

    //this.props.reducer.inRegion && console.log('hello:', this.props.reducer.inRegion)
    return (
      <View style={{marginTop :100}}>
        <Text>geofence test</Text>

      {/**
       * <Button 
          onPress={this._startLocationTrack}
          title="TRACK ME"
        />
       */}
        
        
        <Text>{this.props.reducer.inRegion ? `YOU ARE AT THE VOLLEYBALL COURT` : `YOU ARE NOT AT THE VOLLEYBAL COURT`}</Text>
      </View>
    );
  }
}

const mapStateToProps = (state) => {
    
  const { reducer } = state
  return { reducer }
};

const mapDispachToProps = dispatch => {
  return {
    setEnterRegion: (y) => dispatch({ type: "SET_ENTER_REGION", value: y})
  };
};

export default connect(mapStateToProps, mapDispachToProps)(Home);


//DEFINE TASKS
const TASK_FETCH_LOCATION = 'TASK_FETCH_LOCATION';
const TASK_CHECK_GEOFENCE = 'TASK_CHECK_GEOFENCE';

// 1 define the task passing its name and a callback that will be called whenever the location changes
TaskManager.defineTask(TASK_FETCH_LOCATION, async ({ data: { locations }, error }) => {
  if (error) {
    console.error(error);
    return;
  }
  const [location] = locations;
  try {
      console.log('tracking in background...',location);
     } catch (err) {
    console.error(err);
  }
});

// 2 start the task
Location.startLocationUpdatesAsync(TASK_FETCH_LOCATION, {
  accuracy: Location.Accuracy.Highest,
  distanceInterval: 1, // minimum change (in meters) betweens updates
  deferredUpdatesInterval: 1000, // minimum interval (in milliseconds) between updates
  // foregroundService is how you get the task to be updated as often as would be if the app was open
  foregroundService: {
    notificationTitle: 'Using your location',
    notificationBody: 'To turn off, go back to the app and switch something off.',
  },
});

// 3 Define geofencing task
TaskManager.defineTask(TASK_CHECK_GEOFENCE, ({ data: { eventType, region }, error }) => {
  if (error) {
    // check `error.message` for more details.
    return;
  }
  if (eventType === Location.GeofencingEventType.Enter) {
    console.log("You've entered region:", region);
    //this.props.setEnterRegion({ inRegion: region.identifier })
    const final  = region
    return final
  } else if (eventType === Location.GeofencingEventType.Exit) {
    console.log("You've left region:", region);
    const final  = region
    return final
  }
});

// 4 when you're done, stop it
Location.hasStartedLocationUpdatesAsync(TASK_FETCH_LOCATION).then((value) => {
  if (value) {
    Location.stopLocationUpdatesAsync(TASK_FETCH_LOCATION);
  }
});

Reducer.js

import { combineReducers } from 'redux';

const INITIAL_STATE = {
    hasLocationPermission: null,
    inRegion: null,
    myLocation: {latitude: 40.7634642, longitude: -73.9290698}
};

const ourReducer = (state = INITIAL_STATE, action) => {
    const newState = { ...state };

  switch (action.type) {
        
                    case "SET_ENTER_REGION":
                      return{
                        ...state,
                        inRegion: action.value
                      }
                    break;
  
  }
  return newState;
};


export default combineReducers({
  reducer: ourReducer,
});

App.js

import React, {Component} from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import ourReducer from './store/reducer';
import Home from './Home';
const store = createStore(ourReducer);

export default class App extends Component {

  render(){

    return (
      <Provider store={ store }>
        <Home/>
      </Provider>
    );
  
  }

}

【问题讨论】:

    标签: javascript react-native redux expo


    【解决方案1】:

    将您的 TaskManager.defineTask 逻辑移动到一个单独的 JS 文件中,并在您的 componentDidMount 上对其进行初始化,并为它提供您的操作创建者,以便您可以确保它可以访问您的 redux 操作并在 redux 范围内正确运行。

    // Home.js
    
    import { configureBgTasks } from './bg';
    
    componentDidMount() {
       const {setEnterRegion} = this.props;
       configureBgTasks({ setEnterRegion });
    }
    
    
    // bg.js
    
    export const configureBgTasks = ({ setEnterRegion }) => {
    TaskManager.defineTask(TASK_FETCH_LOCATION, async ({ data: { locations }, error }) => {
      if (error) {
        console.error(error);
        return;
      }
      const [location] = locations;
      try {
          console.log('tracking in background...',location);
         } catch (err) {
        console.error(err);
      }
    });
    
    
    
    // 3 Define geofencing task
    TaskManager.defineTask(TASK_CHECK_GEOFENCE, ({ data: { eventType, region }, error }) => {
      if (error) {
        // check `error.message` for more details.
        return;
      }
      if (eventType === Location.GeofencingEventType.Enter) {
        console.log("You've entered region:", region);
             setEnterRegion();
        const final  = region
        return final
      } else if (eventType === Location.GeofencingEventType.Exit) {
        console.log("You've left region:", region);
        const final  = region
        return final
      }
    });
    }
    

    【讨论】:

    • 感谢您的帮助,它确实帮助我正确设置了我的项目。我想知道,我可以将我的 redux 状态传递给子组件bg 文件吗?我希望能够在bg 文件中的函数中访问我的reducer 中的值。感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-04
    • 1970-01-01
    • 2017-06-23
    • 1970-01-01
    • 2019-03-15
    相关资源
    最近更新 更多