首页 > 解决方案 > 从 API 获取数据时遇到问题

问题描述

我正在尝试从 api 呈现数据(类型:GET)但是当我试图设置它的状态时无法设置我的状态......这是我的状态和 api 调用的代码

constructor(props) {


super()
 constructor(props) {
        super(){this.state={gender:{}}

现在这是我的 api 调用

componentDidMount()
    {
axios.get("http://172.104.217.178/blaze10/public/api/genders")
.then((response) => {
    alert(JSON.stringify(response));
    this.setState({
        gender:response.data


    });
    alert(this.state.gender)

})
.catch(error => alert(JSON.stringify(error.response.data)));
     }

这是我在渲染函数中编写的代码

let gender = [];
  let stateGender = this.state.gender;
  alert(JSON.stringify(this.state.gender));
    stateGender.forEach((value, key) => {
        gender.push(<Picker.Item label={key} value={value} />);
    });

and this is my picker components code where i want to show my api data ..
<Item picker >
        <Left>
       <Text style={{paddingLeft:10,fontSize:15,fontWeight:'bold',color:this.state.backgroundColor2}}> Gender</Text>
       </Left>
       <Body>
          <Picker 
            mode="dropdown"
            iosIcon={<Icon name="ios-arrow-down-outline" />}
            style={{ width: '100%' }}

            placeholder="Select Gender"

            placeholderStyle={{ color: "#bfc6ea" }}
            placeholderIconColor="#007aff"
            selectedValue={this.state.gender1}
            onValueChange={(value)=>this.onValueChange(value,'gender')}


          >
            {/* {gender} */}
          </Picker>
          </Body>
        </Item>

面临问题

  1. 我的状态无法更新
  2. 当我尝试运行我的应用程序时,它会给出这样的错误 TypeError:stateGender is not a function

标签: react-native

解决方案


您的代码中发生了几件事。

首先,在使用 Component 的构造函数时,将 props 传递给 super:

来自官方文档

在挂载之前调用 React 组件的构造函数。在为 React.Component 子类实现构造函数时,您应该在任何其他语句之前调用 super(props)。否则,this.props 将在构造函数中未定义,这可能会导致错误。

代替:

constructor(props) {
    super(){this.state={gender:{}}

和:

constructor(props) {
    super(props);
    {this.state={gender:{}}
}

其次,当您成功调用您的 api 时,您正在使用 setState 正确设置状态,但是您会弹出一个带有 state 值的警报,并且您不能保证已设置状态。

这发生在这里:

this.setState({
    gender:response.data
});
alert(this.state.gender)

由于以下原因,这可能会或可能不会起作用:

来自官方文档

setState() 并不总是立即更新组件。它可能会批量更新或将更新推迟到以后。这使得在调用 setState() 之后立即读取 this.state 是一个潜在的陷阱。相反,使用 componentDidUpdate 或 setState 回调 (setState(updater, callback)),它们都保证在应用更新后触发。

现在,当您渲染组件时,您正在执行以下操作:

let gender = [];
let stateGender = this.state.gender;
stateGender.forEach((value, key) => {
    gender.push(<Picker.Item label={key} value={value} />);
});

由于 stateGender 是一个对象(您将其初始化为this.state={gender:{}}),因此您不能直接使用 forEach 对其进行迭代,而是使用Object.keys获取对象的键,然后遍历对象的键。另外,请确保stateGender已初始化:

if(stateGender){
    Object.keys(stateGender).forEach((key) => {
        if(stateGender.hasOwnProperty(key)){
            gender.push(<Picker.Item label={key} value={stateGender[key]} />);
        }
    });
}

建议

我强烈建议您在渲染中替换此行:

{/* {gender} */}

有了这个:

{
Object.keys(stateGender).forEach((key) => {
    if(stateGender.hasOwnProperty(key)){
        return (<Picker.Item label={key} value={stateGender[key]} />);
    }
});
}

所以你不需要这个gender变量。不要忘记验证是否stateGender不是未定义的,它是一个对象还是有键。

您的组件应如下所示:

 constructor(props){
    super(props);
    this.state = { gender:{} }
  }
  componentDidMount() {
    axios.get("http://172.104.217.178/blaze10/public/api/genders")
      .then((response) => {
        this.setState({
          gender: response.data
        });
      })
      .catch(error => alert(error.message));
  }

  render(){
    let stateGender = this.state.gender;
    // To test if stateGender has keys. If the following alert doesn't return anything, then it will never render the items.
    alert('keys: ' + JSON.stringify(Object.keys(stateGender))); 

    return(
    <View>
      <Left>
        <Text style={{ paddingLeft: 10, fontSize: 15, fontWeight: 'bold', color: this.state.backgroundColor2 }}> Gender</Text>
      </Left>
      <Body>
        <Picker
          mode="dropdown"
          iosIcon={<Icon name="ios-arrow-down-outline" />}
          style={{ width: '100%' }}
          placeholder="Select Gender"
          placeholderStyle={{ color: "#bfc6ea" }}
          placeholderIconColor="#007aff"
          selectedValue={this.state.gender1}
          onValueChange={(value) => this.onValueChange(value, 'gender')}>
          {
            Object.keys(stateGender).forEach((key) => {
              if (stateGender.hasOwnProperty(key)) {
                return (<Picker.Item label={key} value={stateGender[key]} />);
              }
            })
          }
        </Picker>
      </Body>
      </View>
    );
  }

推荐阅读