如何将 Fetch 转换为 Axios,将 Class 组件转换为 Functional 组件?
How to convert Fetch to Axios and Class component to Functional component?
如何将 Fetch 转换为 Axios,将 Class 组件转换为 Functional 组件?
我想学习在React native中使用函数式组件和axios实现Infinite-Scrolling,但是很难应用,因为参考文档是由class组件和fetch组成。
import React from 'react';
import {
View,
Image,
Text,
FlatList, // here
} from 'react-native';
export default class App extends React.Component {
state = {
data: [],
page: 1 // here
}
_renderItem = ({item}) => (
<View style={{borderBottomWidth:1, marginTop: 20}}>
<Image source={{ uri: item.url }} style={{ height: 200}} />
<Text>{item.title}</Text>
<Text>{item.id}</Text>
</View>
);
_getData = () => {
const url = 'https://jsonplaceholder.typicode.com/photos?_limit=10&_page=' + this.state.page;
fetch(url)
.then(r => r.json())
.then(data => {
this.setState({
data: this.state.data.concat(data),
page: this.state.page + 1
})
});
}
componentDidMount() {
this._getData();
}
// here
_handleLoadMore = () => {
this._getData();
}
render() {
return (
<FlatList
data={this.state.data}
renderItem={this._renderItem}
keyExtractor={(item, index) => item.id}
onEndReached={this._handleLoadMore}
onEndReachedThreshold={1}
/>
);
}
}
从 class 转换为函数组件时,这里有几个相关步骤:
- 将
componentDidMount
等生命周期事件替换为 useEffect
。
- 用一个或多个
useState
钩子替换组件状态。
- 将 class 方法转换为普通函数。
- 删除对
this
. 的所有引用
- 删除
render()
并直接 return
JSX。
方法_renderItem
、_getData
、_handleLoadMore
基本不变。它们只是成为 const
变量而不是 class 属性。
这是从 class 到函数组件的直接转换:
import React, { useEffect, useState } from 'react';
import {
View,
Image,
Text,
FlatList,
} from 'react-native';
export default function App() {
const [page, setPage] = useState(1);
const [data, setData] = useState([]);
const _renderItem = ({ item }) => (
<View style={{ borderBottomWidth: 1, marginTop: 20 }}>
<Image source={{ uri: item.url }} style={{ height: 200 }} />
<Text>{item.title}</Text>
<Text>{item.id}</Text>
</View>
);
const _getData = () => {
const url =
'https://jsonplaceholder.typicode.com/photos?_limit=10&_page=' + page;
fetch(url)
.then((r) => r.json())
.then((data) => {
setData(data.concat(data));
setPage(page + 1);
});
};
const _handleLoadMore = () => {
_getData();
};
// useEffect with an empty dependency array replaces componentDidMount()
useEffect(() => _getData(), []);
return (
<FlatList
data={data}
renderItem={_renderItem}
keyExtractor={(item, index) => item.id}
onEndReached={_handleLoadMore}
onEndReachedThreshold={1}
/>
);
}
这是 axios
以及其他一些改进。我注意到在到达初始零长度列表的末尾时调用了 end reached 函数,导致第一页被获取两次。所以实际上不需要 componentDidMount
。我从.then()
改成了async
/await
,不过没关系。
import React, { useEffect, useState } from 'react';
import { View, Image, Text, FlatList } from 'react-native';
import axios from 'axios';
export default function App() {
const [page, setPage] = useState(1);
const [data, setData] = useState([]);
const _renderItem = ({ item }) => (
<View style={{ borderBottomWidth: 1, marginTop: 20 }}>
<Image source={{ uri: item.url }} style={{ height: 200 }} />
<Text>{item.title}</Text>
<Text>{item.id}</Text>
</View>
);
const _getData = async () => {
const url =
'https://jsonplaceholder.typicode.com/photos?_limit=10&_page=' + page;
const res = await axios.get(url);
setData(data.concat(res.data));
setPage(page + 1);
};
const _handleLoadMore = () => {
_getData();
};
// useEffect with an empty dependency array replaces componentDidMount()
useEffect(() => {
// put async functions inside curly braces to that you aren't returing the Promise
_getData();
}, []);
return (
<FlatList
data={data}
renderItem={_renderItem}
keyExtractor={(item, index) => item.id}
onEndReached={_handleLoadMore}
onEndReachedThreshold={1}
/>
);
}
Expo Link -- 它在我的设备上有效,但无限滚动在网络预览中似乎不起作用。
您还可以进行更多“高级”改进:
- 使用先前状态的回调设置状态以确保值始终正确。
setPage(current => current + 1)
setData(current => current.concat(res.data))
- 使用
useCallback
进行记忆,以便像 _renderItem
这样的函数在重新渲染时保持恒定的引用。
- 详尽的
useEffect
依赖项(需要记忆)。
如何将 Fetch 转换为 Axios,将 Class 组件转换为 Functional 组件?
我想学习在React native中使用函数式组件和axios实现Infinite-Scrolling,但是很难应用,因为参考文档是由class组件和fetch组成。
import React from 'react';
import {
View,
Image,
Text,
FlatList, // here
} from 'react-native';
export default class App extends React.Component {
state = {
data: [],
page: 1 // here
}
_renderItem = ({item}) => (
<View style={{borderBottomWidth:1, marginTop: 20}}>
<Image source={{ uri: item.url }} style={{ height: 200}} />
<Text>{item.title}</Text>
<Text>{item.id}</Text>
</View>
);
_getData = () => {
const url = 'https://jsonplaceholder.typicode.com/photos?_limit=10&_page=' + this.state.page;
fetch(url)
.then(r => r.json())
.then(data => {
this.setState({
data: this.state.data.concat(data),
page: this.state.page + 1
})
});
}
componentDidMount() {
this._getData();
}
// here
_handleLoadMore = () => {
this._getData();
}
render() {
return (
<FlatList
data={this.state.data}
renderItem={this._renderItem}
keyExtractor={(item, index) => item.id}
onEndReached={this._handleLoadMore}
onEndReachedThreshold={1}
/>
);
}
}
从 class 转换为函数组件时,这里有几个相关步骤:
- 将
componentDidMount
等生命周期事件替换为useEffect
。 - 用一个或多个
useState
钩子替换组件状态。 - 将 class 方法转换为普通函数。
- 删除对
this
. 的所有引用
- 删除
render()
并直接return
JSX。
方法_renderItem
、_getData
、_handleLoadMore
基本不变。它们只是成为 const
变量而不是 class 属性。
这是从 class 到函数组件的直接转换:
import React, { useEffect, useState } from 'react';
import {
View,
Image,
Text,
FlatList,
} from 'react-native';
export default function App() {
const [page, setPage] = useState(1);
const [data, setData] = useState([]);
const _renderItem = ({ item }) => (
<View style={{ borderBottomWidth: 1, marginTop: 20 }}>
<Image source={{ uri: item.url }} style={{ height: 200 }} />
<Text>{item.title}</Text>
<Text>{item.id}</Text>
</View>
);
const _getData = () => {
const url =
'https://jsonplaceholder.typicode.com/photos?_limit=10&_page=' + page;
fetch(url)
.then((r) => r.json())
.then((data) => {
setData(data.concat(data));
setPage(page + 1);
});
};
const _handleLoadMore = () => {
_getData();
};
// useEffect with an empty dependency array replaces componentDidMount()
useEffect(() => _getData(), []);
return (
<FlatList
data={data}
renderItem={_renderItem}
keyExtractor={(item, index) => item.id}
onEndReached={_handleLoadMore}
onEndReachedThreshold={1}
/>
);
}
这是 axios
以及其他一些改进。我注意到在到达初始零长度列表的末尾时调用了 end reached 函数,导致第一页被获取两次。所以实际上不需要 componentDidMount
。我从.then()
改成了async
/await
,不过没关系。
import React, { useEffect, useState } from 'react';
import { View, Image, Text, FlatList } from 'react-native';
import axios from 'axios';
export default function App() {
const [page, setPage] = useState(1);
const [data, setData] = useState([]);
const _renderItem = ({ item }) => (
<View style={{ borderBottomWidth: 1, marginTop: 20 }}>
<Image source={{ uri: item.url }} style={{ height: 200 }} />
<Text>{item.title}</Text>
<Text>{item.id}</Text>
</View>
);
const _getData = async () => {
const url =
'https://jsonplaceholder.typicode.com/photos?_limit=10&_page=' + page;
const res = await axios.get(url);
setData(data.concat(res.data));
setPage(page + 1);
};
const _handleLoadMore = () => {
_getData();
};
// useEffect with an empty dependency array replaces componentDidMount()
useEffect(() => {
// put async functions inside curly braces to that you aren't returing the Promise
_getData();
}, []);
return (
<FlatList
data={data}
renderItem={_renderItem}
keyExtractor={(item, index) => item.id}
onEndReached={_handleLoadMore}
onEndReachedThreshold={1}
/>
);
}
Expo Link -- 它在我的设备上有效,但无限滚动在网络预览中似乎不起作用。
您还可以进行更多“高级”改进:
- 使用先前状态的回调设置状态以确保值始终正确。
setPage(current => current + 1)
setData(current => current.concat(res.data))
- 使用
useCallback
进行记忆,以便像_renderItem
这样的函数在重新渲染时保持恒定的引用。 - 详尽的
useEffect
依赖项(需要记忆)。