Методы жизненного цикла ReactJS не работают последовательно - PullRequest
0 голосов
/ 23 марта 2019

Я работаю над рендерингом карт Google в ReactJS. Для этого я использую библиотеку «act-google-maps ». Логический поток есть; при загрузке страницы найдите местоположение пользователя и нанесите его на карту. Пользователю предоставляются навигационные ссылки для перехода на другой URL. Для управления навигацией я использую роутер React. Местоположение пользователя идентифицируется в componentWillMount (), затем устанавливается соответствующее состояние, и карта отображается в render (). Проблема в том, что render () вызывается перед завершением componentWillMount (), он получает нулевые значения и завершается ошибкой. Эта ситуация возникает только при маршрутизации на стороне клиента, а не при рендеринге на стороне сервера.

Чтобы ограничить способ выполнения, я сделал componentWillMount () как асинхронный метод, в котором он ожидает, пока не будет определено местоположение пользователя. Тем не менее, это не помогло.

state = {
        homeLocation: {},
        coordinates: []
    }

async componentWillMount(props) {
        const { lat,lng } = await this.getcurrentLocation();
        this.setState({
            homeLocation:{
                lat: lat, 
                lng: lng
            }
        })
    }

getcurrentLocation() {

        if (window.navigator && window.navigator.geolocation) {
          return new Promise((resolve, reject) => {
            window.navigator.geolocation.getCurrentPosition(pos => {
              const coords = pos.coords;
              resolve({
                lat: coords.latitude,
                lng: coords.longitude
              });
            });
          });
        }
        return {
          lat: 0,
          lng: 0
        };
      }
render(){

   <MapWithAMarker
   // necessary parameters
  />
}

//Routers
const AppRouter = () => (
    <Router>
        <div>
            <Switch>
                <Route path="/" component={MapHomeLocation} exact={true}/>
                <Route path="/location/:locationType" component={MapSelectedLocation}/>
                <Route component={Notfound}/>
            </Switch>
        </div>

    </Router>
);


The expected result is that coordinates should be determined first then render() should get called. In server-side routing(i.e. using anchor tags instead of <Link>) it works as expected.

Ответы [ 3 ]

1 голос
/ 23 марта 2019

Вы должны проверить таким образом, если в этом есть данные, а затем дать только значение.

, если data && data.length> 0?данные: ноль

1 голос
/ 23 марта 2019

Никогда не выполняйте операции выборки в componentWillMount(), вместо этого используйте componentDidMount(), так как вызов setState() приведет к повторной визуализации компонента, вы, вероятно, увидите новые данные на вашей карте.

1 голос
/ 23 марта 2019

Вызовите getcurrentLocation () в самом состоянии.

state = {
        homeLocation: this.getcurrentLocation(),
        coordinates: []
    }



getcurrentLocation() {

        if (window.navigator && window.navigator.geolocation) {
          return new Promise((resolve, reject) => {
            window.navigator.geolocation.getCurrentPosition(pos => {
              const coords = pos.coords;
              resolve({
                lat: coords.latitude,
                lng: coords.longitude
              });
            });
          });
        }
        return {
          lat: 0,
          lng: 0
        };
      }
render(){

   <MapWithAMarker
   // necessary parameters
  />
}

//Routers
const AppRouter = () => (
    <Router>
        <div>
            <Switch>
                <Route path="/" component={MapHomeLocation} exact={true}/>
                <Route path="/location/:locationType" component={MapSelectedLocation}/>
                <Route component={Notfound}/>
            </Switch>
        </div>

    </Router>
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
...