iRo*_*tia 13 reactjs react-native
我正在使用congap api来首先获取大约1500+加密货币的数据,然后使用Web-socket来更新加密货币的更新值.
我在这里使用redux来管理我的状态
在我的内部componentDidMount()
,我正在调用一个可以获取硬币价值的redux动作 fetchCoin
componentDidMount() {
this.props.fetchCoin()
}
Run Code Online (Sandbox Code Playgroud)
然后在return
我做这样的事情
<FlatList
data={this.state.searchCoin ? displaySearchCrypto : this.props.cryptoLoaded}
renderItem={({ item }) => (
<CoinCard
key={item["short"]}
coinShortName = {item["short"]}
coinName = {item["long"]}
coinPrice = {item["price"].toFixed(2)}
percentChange = {item["perc"].toFixed(2)}
/>
Run Code Online (Sandbox Code Playgroud)
然后我有一个web-socket来更新加密货币的价值
componentDidUpdate() {
if (this.state.updateCoinData || this.updateCoinData.length < 1 ) {
this.updateCoinData = [...this.props.cryptoLoaded];
this.setState({updateCoinData: true})
}
this.socket.on('trades', (tradeMsg) => {
for (let i=0; i< this.updateCoinData.length; i++) {
if (this.updateCoinData[i]["short"] == tradeMsg.coin ) {
//Search for changed Crypto Value
this.updateCoinData[i]["perc"] = tradeMsg["message"]["msg"]["perc"]
this.updateCoinData[i]["price"] = tradeMsg['message']['msg']['price']
//Update the crypto Value state in Redux
this.props.updateCrypto(this.updateCoinData);
}
}
})
}
Run Code Online (Sandbox Code Playgroud)
现在,虽然这项工作,问题是这会让我的应用程序像地狱一样慢,因为每当套接字发送新数据时,它必须呈现每个组件,因此触摸和搜索等事件需要花费大量时间来执行.[更新]事实证明我的应用程序正在渲染一些东西如果我删除套接字连接,请查看更新2
[问题:]我应该怎样做才能提高App的性能?(不喜欢使用状态或使用DOM来更新我的应用程序等等).
[更新1:]我用的https://github.com/irohitb/Crypto而这两个是js文件,所有的逻辑正在发生 https://github.com/irohitb/Crypto/blob/master/src/container /cryptoContainer.js https://github.com/irohitb/Crypto/blob/master/src/components/CoinCard.js 我也从map转到Flatlist.
[更新:2]我发现在我的应用程序中发生了无休止的渲染,这可能让我的线程忙碌(我的意思是它是无穷无尽的,不必要地传递道具).我在单独的Stackoverflow线程上问了同样的问题,但没有得到正确的响应,因为它与性能有关,我想在这里给它一个赏金.
请检查此线程:无限渲染React
[答案更新:]虽然这里有很多很好的答案,但万一有人想了解它是如何工作的,你可以克隆我的存储库并在此提交之前返回.我已将提交链接到我的问题已解决的位置(因此您可能需要返回并查看我做错了什么).此外,所有答案都非常有用,不难理解,所以你一定要仔细阅读.
每次组件更新时,它都会启动一个新的套接字,导致内存泄漏,并导致this.props.updateCrypto(updateCoinData);
对同一数据多次调用.这可以通过打开插座componentDidMount()
并将其关闭来解决componentWillUnmount()
.
您还可以缓冲多个记录更新,并每隔几秒钟一次更改FlatList数据.
编辑,工作示例(App.js):
import React, { Component } from 'react';
import { Text, View, FlatList } from 'react-native';
import SocketIOClient from 'socket.io-client';
type Props = {};
export default class App extends Component<Props> {
constructor(props) {
super(props);
this.currencies = {};
this.state = {
currenciesList: [],
}
}
componentDidMount() {
this.socket = SocketIOClient('https://coincap.io');
this.socket.on('trades', (tradeMsg) => {
const time = new Date();
// Store updates to currencies in an object
this.currencies[tradeMsg.message.msg.short] = {
...tradeMsg.message.msg,
time: time.getHours() + ':' + time.getMinutes() + ':' + time.getSeconds(),
};
// Create a new array from all currencies
this.setState({currenciesList: Object.values(this.currencies)})
});
}
componentWillUnmount() {
this.socket.disconnect();
}
render() {
return (
<FlatList
data={this.state.currenciesList}
extraData={this.state.currenciesList}
keyExtractor={(item) => item.short}
renderItem={({item}) => <View style={{flexDirection: 'row', justifyContent: 'space-between'}}>
<Text style={{flex: 1}}>{item.time}</Text>
<Text style={{flex: 1}}>{item.short}</Text>
<Text style={{flex: 1}}>{item.perc}</Text>
<Text style={{flex: 1}}>{item.price}</Text>
</View>}
/>
);
}
}
Run Code Online (Sandbox Code Playgroud)
有许多标准方法可以提高应用程序的性能,最常见的是:
不要在优化之前处理数据 - 格式化未更改的数据至少是不必要的.您可以插入中间组件(优化层),该组件将<CoinCard />
仅将格式化数据传递/更新为"原始数据"更改.
您可能不需要终极版在所有(在状态存储数据)当数据在同一个地方/结构简单,使用.当然,您可以将redux用于其他全局共享应用程序状态(fe过滤选项).
使用<FlatList />
(react-native),搜索更合适?
有些代码在平均时间(repo)中发生了变化,此时(08.09)仍存在一个问题,可能导致内存泄漏.
您正在呼叫this.socket.on
每个componentDidUpdate
呼叫(错误编码的条件) - 不断添加新的处理程序!
componentDidUpdate() {
// call all ONLY ONCE afer initial data loading
if (!this.state.updateCoinData && !this.props.cryptoLoaded.length) {
this.setState({updateCoinData: true}) // block condition
this.socket.on('trades', (tradeMsg) => {
// slice() is faster, new array instance
// let updateCoinData = [...this.props.cryptoLoaded];
let updateCoinData = this.props.cryptoLoaded.slice();
for (let i=0; i<updateCoinData.length; i++) {
//Search for changed Crypto Value
if (updateCoinData[i]["short"] == tradeMsg.coin ) {
// found, updating from message
updateCoinData[i]["long"] = tradeMsg["message"]["msg"]["long"]
updateCoinData[i]["short"] = tradeMsg["message"]["msg"]["short"]
updateCoinData[i]["perc"] = tradeMsg["message"]["msg"]["perc"]
updateCoinData[i]["mktcap"] = tradeMsg['message']['msg']["mktcap"]
updateCoinData[i]["price"] = tradeMsg['message']['msg']['price']
//Update the crypto Value state in Redux
this.props.updateCrypto(updateCoinData);
// record found and updated, no more looping needed
break;
}
}
})
}
}
Run Code Online (Sandbox Code Playgroud)
次要错误:初始提取状态在reducer中设置为true.
搜索性能问题我会看<CoinCard />
:
increased
并且decreased
不需要在强制不必要的渲染调用的状态下保存;updateCoinData
上面的代码中)并且仅为可见项导出方向(仅检查0和符号)差异(已计算perc
)(来自渲染)并且仅在时间限制期间(渲染时间和数据更新道具之间的差异).也可以用.setTimeout
componentWillReceiveProps
,componentDidUpdate
并且shouldComponentUpdate
(高度?)提高性能;正如 Bhojendra Rauniyar 所说,您应该在 CoinCard 中使用 shouldComponentUpdate。您可能还想更改您的 FlatList,缩小的示例在 ScrollView 中具有 FlatList,这会导致 FlatList 完全展开,从而立即渲染其所有项目。
class cryptoTicker extends PureComponent {
componentDidMount() {
this.socket = openSocket('https://coincap.io');
this.props.fetchCoin()
this.props.CurrencyRate()
this.socket.on('trades', (tradeMsg) => {
for (let i=0; i< this.updateCoinData.length; i++) {
if (this.updateCoinData[i]["short"] == tradeMsg.coin ) {
//Search for changed Crypto Value
this.updateCoinData["short"] = tradeMsg["message"]["msg"]["short"]
this.updateCoinData[i]["perc"] = tradeMsg["message"]["msg"]["perc"]
this.updateCoinData[i]["price"] = tradeMsg["message"]['msg']['price']
//Update the crypto Value state in Redux
this.props.updateCrypto(this.updateCoinData);
}
}
})
}
componentWillReceiveProps(newProps){
// Fill with redux data once
if (this.updateCoinData.length < 1 && newProps.cryptoLoaded) {
this.updateCoinData = [...newProps.cryptoLoaded];
}
}
render() {
return (
<View style={{height: '100%'}}>
<Header/>
<FlatList
style={{flex:1}}
data={this.props.cryptoLoaded}
keyExtractor={item => item.short}
initialNumToRender={50}
windowSize={21}
removeClippedSubviews={true}
renderItem={({item, index}) => (
<CoinCard
index={index}
{...item}
/>
)}
/>
</View>
)
}
}
class CoinCard extends Component {
shouldComponentUpdate(nextProps) {
return this.props.price !== nextProps.price || this.props.perc !== nextProps.perc
}
render() {
console.log("here: " + this.props.index);
return (
<View>
<Text> {this.props.index} = {this.props.long} </Text>
</View>
)
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
950 次 |
最近记录: |