最好在componentDidMount或componentWillMount上执行API调用吗?

时间:2019-02-20 00:51:17

标签: javascript reactjs ecmascript-6

我正在尝试找出执行api调用的最佳方法。我需要在组件加载时获取数据,而不是在任何onClick / onPress方法上获取数据。 这是使用访存的api调用:

import { Alert, AsyncStorage } from 'react-native';
import { has } from 'lodash';
import PropTypes from 'prop-types';
import { compose } from 'redux';
import { connect } from 'react-redux';
import { passengersDataAction } from '../screens/HomeScreen/actions/homeScreen';

const GetPassengersData = async (
  username,
  password,
  navigation,
  passengersDataActionHandler,
) => {
  try {
    const response = await fetch(
      'http://myAPI/public/api/getPassengers',
      {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${868969}`,
          Accept: 'application/json',
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ email: username, password }),
      },
    );
    const responseJson = await response.json();
    if (has(responseJson, 'error')) {
      Alert.alert('Error', 'Please check your credentials.');
    } else {
      await AsyncStorage.setItem('userToken', responseJson.success.token);
      passengersDataActionHandler(responseJson.success.token);
      navigation.navigate('App');
    }
  } catch (error) {
    Alert.alert(
      'Error',
      'There was an error with your request, please try again later.',
    );
  }
};

GetPassengersData.propTypes = {
  navigation: PropTypes.shape({}).isRequired,
  passengersDataActionHandler: PropTypes.func.isRequired,
};

export default compose(
  connect(
    store => ({
      userToken: store.signinScreen.userToken,
      passengersData: store.homeScreen.passengersData,
    }),
    dispatch => ({
      passengersDataActionHandler: token => {
        dispatch(passengersDataAction(token));
      },
    }),
  ),
)(GetPassengersData);

通话将在这里执行:

class AllPassengers extends Component {
  compo
  render() {
    return (
      <ScrollView>
        <View style={{ height: 50 }} />
        <View
          style={[
            tabViewStyles.container,
            { alignItems: 'center', justifyContent: 'center' },
          ]}
        >
          <Text style={{ fontWeight: 'bold' }}>
            Select passengers to start your route
          </Text>
          <View style={{ height: 50 }} />
          <PassengersCircle />
        </View>
        <AllPassengersList />
      </ScrollView>
    );
  }
}

export default AllPassengers;

我还想知道是否有办法在功能/无状态组件上进行该调用?

2 个答案:

答案 0 :(得分:1)

componentWillMount()在挂载发生之前被调用。它在render()之前被调用,因此在获取数据时,已经调用了render(),组件应该能够在没有任何数据的情况下进行渲染。

建议在React Docs上获取componentDidMount()中的数据。

  

避免在此方法中引入任何副作用或订阅。   对于这些用例,请改用componentDidMount()。

componentWillMount将被标记为“旧版”。它仍然有效,但不推荐。

  

注意

     

此生命周期以前称为componentWillMount。该名称将一直使用到版本17。   重命名不安全生命周期codemod以自动更新您的   组件。

选中此项以查看how to fetch data in a functional component

上面链接中的片段:

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

function App() {
  const [data, setData] = useState({ hits: [] });

  useEffect(async () => {
    const result = await axios(
      'http://hn.algolia.com/api/v1/search?query=redux',
    );

    setData(result.data);
  });

  return (
    <ul>
      {data.hits.map(item => (
        <li key={item.objectID}>
          <a href={item.url}>{item.title}</a>
        </li>
      ))}
    </ul>
  );
}

export default App;

答案 1 :(得分:0)

从React 16.3开始,

componentWillMount被认为是“旧版”,并在函数名称前添加了“ UNSAFE”,以便清楚地说明这一点:https://reactjs.org/docs/react-component.html#unsafe_componentwillmount,它将在即将发布的React版本中完全删除。 (17.0)。您可以在React blog中阅读有关此内容的更多信息,但关键语录可能是:

  

[componentWillMount]对于服务器渲染(将不使用外部数据)和即将到来的异步渲染模式(其中请求可能多次发起)都是有问题的。

因此,要使组件正常工作,您应该在componentDidMount中执行数据提取。

要在功能组件中执行此操作,您可以使用“ Hooks”的新React功能。这样就可以在功能组件中使用类组件的某些状态突变功能。