【问题标题】:Use static fetch service使用静态抓取服务
【发布时间】:2021-04-03 20:42:36
【问题描述】:

我创建了一个 express mongoose api。我想从我的 React 应用程序中使用该 api。

我想创建一个服务来管理这些 api 请求。但是我是 react-native 的新手,我不能使用该服务。我尝试创建一个静态类,但无法使其正常工作。这是一个例子:

// apiService.js
class ApiService {
    static fetchUsers = () => {
        return fetch('XXX/users')
            .then((response) => {
                return response.json()
                    .then((data) => {
                        return data;
                    })
            })
            .catch((error) => {
                console.error(error);
            });
    }
}

export default ApiService;

还有我的屏幕

// UserScreen.js
import ApiService from '../services/apiService';

export default class UserScreen extends Component {
     constructor(props) {
        super(props);

        this.state = {
            users: [],
            isLoading: true,
        }
    }

    componentDidMount = () => {
       let users = ApiService.fetchUsers();
       this.setState({data: users});
       this.setState({isLoading: false});
    }

    render() {
        if (this.state.isLoading) {
            return (
                <View style={styles.container}>
                    <ActivityIndicator/>
                </View>
            )
        } else {
            return (
                <View style={{ flex: 1, marginTop: 100 }}>
                    {
                        this.state.data.map((val, key) => {
                            return <TouchableOpacity
                                style={styles.homeButton}
                                key={key}
                                onPress={() => this.redirectHandler(val)}>
                            </TouchableOpacity>
                        })
                    }
                </View>
            )
        }
    }


}

我尝试使用异步并等待,但找不到检索数据的方法。数据可以在 apiService 中很好地检索,但我无法与 UserScreen 共享它们。

如何在 react-native 中使用(静态或非静态)类/函数并从屏幕获取数据

更新 这是我尝试使用异步的方法

class ApiService {
    static fetchUsers = async () => {
        try {
            let response = await fetch('XXXXX/users/');
            let json = await response.json();
            return json;
        } catch (error) {
            console.error(error);
        }
    }
}

export default ApiService;

在我的用户屏幕中

componentDidMount = async () => {
        try {
            let users = await ApiService.fetchUsers();
            this.setState({isLoading: false});
            this.setState({data: users});
        } catch (error) {
            console.log(error);
        }
    }

【问题讨论】:

  • 这与类或静态方法无关。只是您的 fetchUsers 函数返回了一个承诺。请向我们展示您如何尝试使用 async/await。
  • @Bergi 我已经更新了我的答案。我对这一切都很陌生,我不明白如何使用 Promise 并检索它的值
  • 您不必两次设置状态。只需将两个键合并到一个 setState 中
  • 这种方法应该有效(除了重复的错误处理)。发生了什么,你遇到了什么问题?
  • @Hearner 这是因为您的第一个 this.setState({ isLoading: false }) 在您的第二个实际提供数据之前导致重新渲染。因此,在 render() 中,您在设置 data 之前采用了 else 分支。

标签: javascript react-native fetch


【解决方案1】:

问题在于您执行两次的 setState。如果您查看组件的逻辑,首先我们检查 isLoading,如果为 true,我们会显示一些消息/微调器,否则我们会显示用户/数据列表。

设置状态的顺序:

this.setState({isLoading: false});
this.setState({data: users});

请注意,每个 setState 都会触发组件的重新渲染,因此在这种情况下,我们首先将 isLoading 设置为 false(第一次重新渲染),然后设置数据(第二次重新渲染)

问题是,当 1st Re-Render 完成时,isLoading 被设置为 false 并且我们上面谈到的条件现在进入“显示用户/数据列表”部分。这里要注意的另一件事是我们在状态中定义了users: [],当我们设置用户数组(来自api调用)时,我们将其设置在一个名为data的变量中。变量data 从未在状态中定义,因此本质上它是“未定义”。

代码中的问题:

this.state.data.map(...)

您不能映射未定义的变量,这就是问题所在。这样做会引发“无法读取未定义的属性映射”的错误。

解决这个问题:

在设置用户列表时,不要做this.setState({ data: users }),而是做this.setState({ users: users })并将this.state.data.map(更改为users.map(

此外,不必要的重新渲染代价高昂,在 React Native 的情况下,它们的代价更高。尽可能合并您的 setState(...) 调用。例如,

this.setState({
    isLoading: false,
    users: users
})

【讨论】:

  • 我不知道使用 setState 重新渲染组件...这解释了错误。非常感谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多