API
によって_React Native
_アプリとfetch
からデータを取得します。 API
からデータを取得するカスタムフックを作成しました。そして私は5秒ごとにそれを再レンダリングする必要があります。それは私のカスタムフックをSetIntervalに包んだし、私のアプリが非常にゆっくり仕事をすると、私が別の画面に移動すると、このエラーが発生します。
マウント解除されていないコンポーネントでReact状態更新を実行できません。これはNO OPですが、アプリケーションのメモリリークを示します。修正するには、UseEffect Cleanup関数ですべてのサブスクリプションと非同期タスクをキャンセルします。
私はこのバグを解決する方法を教えてください。私はsetInterval
に最適な方法になるでしょう。
私のカスタムフック:
_export const useFetch = url => {
const [state, setState] = useState({ data: null, error: false, loading: true })
useEffect(() => {
setInterval(() => {
setState(state => ({ data: state.data, error: false, loading: true }))
fetch(url)
.then(data => data.json())
.then(obj =>
Object.keys(obj).map(key => {
let newData = obj[key]
newData.key = key
return newData
})
)
.then(newData => setState({ data: newData, error: false, loading: false }))
.catch(function(error) {
console.log(error)
setState({ data: null, error: true, loading: false })
})
}, 5000)
}, [url, useState])
useEffect(() => () => console.log('unmount'), [])
return state
}
_
私のコンポーネント:
_const ChartsScreen = ({ navigation }) => {
const { container } = styles
const url = 'https://poloniex.com/public?command=returnTicker'
const { data, error, loading } = useFetch(url)
const percentColorHandler = number => {
return number >= 0 ? true : false
}
return (
<View style={container}>
<ProjectStatusBar />
<IconsHeader
dataError={false}
header="Charts"
leftIconName="ios-arrow-back"
leftIconPress={() => navigation.navigate('Welcome')}
/>
<ChartsHeader />
<ActivityIndicator animating={loading} color="#068485" style={{ top: HP('30%') }} size="small" />
<FlatList
data={data}
keyExtractor={item => item.key}
renderItem={({ item }) => (
<CryptoItem
name={item.key}
highBid={item.highestBid}
lastBid={item.last}
percent={item.percentChange}
percentColor={percentColorHandler(item.percentChange)}
/>
)}
/>
</View>
)
}
_
それは両方のことかもしれません:
コード:
useEffect(() => {
let isMounted = true
const intervalId = setInterval(() => { //assign interval to a variaable to clear it
setState(state => ({ data: state.data, error: false, loading: true }))
fetch(url)
.then(data => data.json())
.then(obj =>
Object.keys(obj).map(key => {
let newData = obj[key]
newData.key = key
return newData
})
)
.then(newData => {
if(!isMounted) return // This will cancel the setState when unmounted
setState({ data: newData, error: false, loading: false })
})
.catch(function(error) {
console.log(error)
setState({ data: null, error: true, loading: false })
})
}, 5000)
return () => {
clearInterval(intervalId); //This is important
isMounted = false // Let's us know the component is no longer mounted.
}
}, [url, useState])
_
サーバーの応答時間に応じて、保留中のクエリにフェイルセーフを追加したい場合があります(例、最初の1つの戻り値の前に次の起動が行われた場合は例)。