类组件到功能组件

时间:2019-10-07 21:55:23

标签: reactjs

我正在尝试将该类组件变成一个功能组件,该组件仅发送回经度和纬度。类组件确实给了我long / lat,但我想将其用作函数。该函数应只返回经度和纬度。

我试图使其内部具有这些函数,但是在navigator.getcurrent中调用了回调函数getCoords ....时,出现错误,表明未分配。

import React, { Component } from 'react';


class App extends Component {

  constructor(props) {
    super(props);
    this.state = {
      lat: '',
      long: ''
    };
  }
  getLocation = () => {
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(this.getCoords)
    } else {
      alert('GeoLocation not enabled');
    }
  }

  getCoords = pos => {
    console.log(pos)
    this.setState({
      lat: pos.coords.latitude,
      long: pos.coords.longitude
    })
  }

  render() {
    return (
      <div>
        <button onClick={this.getLocation}>Click me</button>
        <p>lat: {this.state.lat}</p>
        <p>long {this.state.long}</p>
      </div>
    );
  }
}

export default App;

我是否必须学习react hooks才能解决我的功能组件问题?

3 个答案:

答案 0 :(得分:1)

使用钩子绝对是必经之路,这样您仍然可以将位置数据保持在状态。这是相同的代码,但带有useState钩子:

process

您会发现这并没有太大的区别,主要是删除const App = () => { const [pos, setPos] = useState({lat: "", long: ""}) const getLocation = () => { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(getCoords) } else { alert('GeoLocation not enabled'); } } const getCoords = (pos) => { console.log(pos) setPos({ lat: pos.coords.latitude, long: pos.coords.longitude }) } return ( <div> <button onClick={getLocation}>Click me</button> <p>lat: {pos.lat}</p> <p>long {pos.long}</p> </div> ); } export default App; this关键字,并用this.statepos.lat替换它们。

从这里开始,如果您希望组件仅返回坐标而不是JSX,则可以创建自己的自定义钩子,如下所示:

setPos

答案 1 :(得分:0)

问题在于,通过导航器获取坐标是异步请求,因此在坐标可用之前就无法进行获取。使用useEffect钩子,您可以告诉它一旦lat和long更新,就可以获取数据,如下所示:

const App = () => {
    const pos = usePos()


    useEffect(() => {
        getDataWithCoords()
    }, [pos.lat, pos.long])

    const getDataWithCoords = () => {
        fetch(`https://maps.googleapis.com/maps/api/geocode/json?latlng=${pos.lat},${pos.long}&key=YOUR_API_KEY`)
            .then(res => res.json())
            .then(res => console.log(res))
            .catch(err => console.log(err))
    }

    return (
        <div>
            <p>Lat {pos.lat}</p>
            <p>Long: {pos.long}</p>
        </div>
    )
}

可能不是一个完美的例子,但它可以工作!

此外,请确保您没有公开发布API密钥,但您希望将这些密钥对您的本地开发环境保持私有。祝你好运!

答案 2 :(得分:0)

这更多地实现了DRY范例,我觉得这是一个相当理想的解决方案。

import React, { useEffect, useState } from 'react';

export function App() {
  const [loc, setLoc] = useState({});
  const [isLoaded, setIsLoaded = useState(false);

  useEffect(() => {
     const fetchMap = async () => {
       const response = await fetch(`https://maps.googleapis.com/maps/api/geocode/json?latlng=${loc.lat},${loc.long}&key=${INSERT_API_KEY_HERE}`);

       // Do something with the response

       setIsLoaded(true);
     };

    fetchMap();
  });


  const getLocation = () => {
    const { geolocation } = navigator;

    if (geolocation) {
      geolocation.getCurrentPosition(getCoordinates);
    } else {
      alert('GeoLocation not enabled');
    }
  };

  const getCoordinates = (pos) => {
    const { latitude, longitude } = pos.coords;
    setLoc({ lat: latitude, long: longitude });
  }; 

  // You can this conditionalize your return statement based
  // on the isLoaded state variable. "if (isLoaded)"

  return (
    <div>
      <button onClick={getLocation}>Click me</button>
      <p>lat: {loc.lat}</p>
      <p>long {loc.long}</p>
    </div>
  );
};

export default App;