[英]React Native: TextInput with state and AsyncStorage
When typing on the keyboard I was seeing some warnings about the input being ahead of the JS code.. 在键盘上键入时,我看到一些关于输入的警告在JS代码之前。
Native TextInput(react native is awesome) is 4 events ahead of JS - try to make your JS faster. 原生TextInput(本机反应很棒)是JS之前的4个事件 - 尝试让你的JS更快。
So added the debounce
and got this to "work": 所以添加了debounce
并debounce
“工作”:
...
import { debounce } from 'lodash'
...
export default class App extends React.Component {
constructor(props) {
super(props)
this.state = {
data,
indexRef: data.reduce((result, item, index) => {
result[item.title] = index
return result
}, {}),
ready: false,
}
this.updatePitch = this.updatePitch.bind(this)
this.saveLocally = debounce(this.saveLocally, 300).bind(this)
}
...
updatePitch(id, text) {
// Copy the data
let data = [...this.state.data]
const index = data.findIndex(obj => obj.id == id)
data[index].pitch = text
// Update the state
this.setState({ data }, this.saveLocally(data))
}
saveLocally(data) {
try {
AsyncStorage.setItem('data', JSON.stringify(data))
this.forceUpdate()
} catch (error) {
// Well..
}
}
render() {
...
BTW: I'm doing some "prop drilling" for now - but planning to do use the Context API (react 16.3) 顺便说一句:我现在正在做一些“道具钻探” - 但计划使用Context API(做出反应16.3)
The warning seems to have gone by adding debounce
(1).. But I'm seeing some strange issues - particularly on the iPhone 8 plus
simulator (not seeing the same on iPhone 6 simulator or Android device) 警告似乎已经通过添加debounce
(1)而消失了。但我看到了一些奇怪的问题 - 特别是在iPhone 8 plus
模拟器上(在iPhone 6模拟器或Android设备上看不到相同)
Issues observed: 发现的问题:
TextInput
don't expand - it just add scolling (expands on iPhone 6 and Android device) TextInput
不会扩展 - 只需添加scolling(在iPhone 6和Android设备上展开) FlatList
- seems like it has problems finding correct height of list elements.. FlatList
中的一些布局问题 - 似乎在查找列表元素的正确高度时遇到了问题。 state
and AsyncStorage
? 快速JS代码和保存到state
和AsyncStorage
的最佳实践是什么? (1) One other way than using debounce
could be to use getDerivedStateFromProps and add some sort of timer pushing the state to the parent component after some period of time.. But wasn't sure that this would make the JS code faster. (1)的另一种方式比使用debounce
可以使用getDerivedStateFromProps和添加某种计时器的一段时间后推的状态到母部件的..但不能肯定,这将让JS代码更快。 So didn't try it. 所以没试过。
I open sourced the entire code since it is too hard to give all the needed information in a SO post when the code is so nested. 我开源了整个代码,因为当代码嵌套时很难在SO帖子中提供所有需要的信息。
The entire code is here: https://github.com/Norfeldt/LionFood_FrontEnd 整个代码在这里: https : //github.com/Norfeldt/LionFood_FrontEnd
(I know that my code might seem messy, but I'm still learning..) (我知道我的代码可能看起来很乱,但我还在学习..)
I don't expect people to go in and fix my code with PR (even though it would be awesome) but just give me some code guidance on how to proper deal with state
and AsyncStorage
for TextInput
. 我不希望人们进入并使用PR修复我的代码(即使它会很棒),但只是给我一些关于如何正确处理state
和TextInput
AsyncStorage
代码指导。
I know I have some style issues - would love to fix them, but also comply with SO and keep it on topic. 我知道我有一些风格问题 - 很想修复它们,但也要遵守SO并保持主题。
I removed forceUpdate
and replaced FadeImage
with just vanilla react native Image
. 我删除了forceUpdate
并用vanilla react本机Image
替换了FadeImage
。
but I'm still seeing some weird issues 但我仍然看到一些奇怪的问题
Here is my code 这是我的代码
import React from 'react'
import {
StyleSheet,
SafeAreaView,
FlatList,
StatusBar,
ImageBackground,
AsyncStorage,
Platform,
} from 'react-native'
import SplashScreen from 'react-native-splash-screen'
import LinearGradient from 'react-native-linear-gradient'
import { debounce } from 'lodash'
import Section from './Section'
import ButtonContact from './ButtonContact'
import { data } from '../data.json'
export default class App extends React.Component {
constructor(props) {
super(props)
this.state = {
data,
indexRef: data.reduce((result, item, index) => {
result[item.title] = index
return result
}, {}),
ready: false,
}
}
async componentDidMount() {
SplashScreen.hide()
try {
let BusinessPlan = await AsyncStorage.getItem('BusinessPlan')
if (BusinessPlan !== null) {
// We have data!!
let data = JSON.parse(BusinessPlan)
data = this.state.data.map(item => {
const index = data.findIndex(obj => obj.id == item.id)
const pitch = index >= 0 ? data[index].pitch : ''
return { ...item, pitch }
})
this.setState({ data, ready: true })
} else {
this.setState({ ready: true })
}
} catch (error) {
// Error retrieving data
}
}
updatePitch = (id, text) => {
// Copy the data
let data = [...this.state.data]
const index = data.findIndex(obj => obj.id == id)
data[index].pitch = text
// Update the state
this.setState({ data }, this.saveLocally(data))
}
saveLocally = data => {
try {
AsyncStorage.setItem('BusinessPlan', JSON.stringify(data))
} catch (error) {
// Well..
}
}
render() {
return (
<LinearGradient
style={{ flex: 1 }}
start={{ x: 0.0, y: 0.25 }}
end={{ x: 0.5, y: 1.0 }}
colors={['#000000', '#808080', '#000000']}
>
<StatusBar
barStyle={'light-content'}
backgroundColor={Platform.OS == 'iOS' ? 'transparent' : 'black'}
/>
<SafeAreaView>
<ImageBackground
source={require('../images/BackgroundImage.png')}
style={{ width: '100%', height: '100%' }}
resizeMode={'cover'}
>
<FlatList
data={this.state.data}
initialNumToRender="16"
keyExtractor={item => item.id}
renderItem={({ item }) => (
<Section
id={item.id}
title={item.title}
pitch={item.pitch}
updatePitch={debounce(this.updatePitch, 1000)}
questions={item.questions}
ready={this.state.ready}
/>
)}
ListFooterComponent={<ButtonContact />}
style={{
backgroundColor: 'transparent',
borderColor: '#000',
borderWidth: StyleSheet.hairlineWidth,
}}
/>
</ImageBackground>
</SafeAreaView>
</LinearGradient>
)
}
}
const styles = StyleSheet.create({
sectionHeader: {
fontSize: 24,
marginHorizontal: 5,
},
})
(I also updated my git repo) (我也更新了我的git repo)
It seems that the setup I have for state
and AsyncStorage
works fine with a debounce
. 似乎我对state
和AsyncStorage
的设置在debounce
工作正常。 The issues I was seeing was because I'm draining the CPU (next step to fix). 我看到的问题是因为我正在耗尽CPU(下一步要修复)。
I tried your code: 我试过你的代码:
"I'm seeing some strange issues - particularly on the iPhone 8 plus simulator (not seeing the same on iPhone 6 simulator or Android device)" ==> I confirmed this “我看到一些奇怪的问题 - 特别是在iPhone 8 plus模拟器上(在iPhone 6模拟器或Android设备上没有看到相同的内容)”==>我证实了这一点
The app takes about 100% CPU. 该应用程序需要大约100%的CPU。
After a while trying I figured out: 经过一段时间的尝试,我发现:
"I'm seeing some strange issues - particularly on the iPhone 8 plus simulator (not seeing the same on iPhone 6 simulator or Android device)" ==> doesn't right, just wait a little TextInput
will expand. “我看到一些奇怪的问题 - 特别是在iPhone 8 plus模拟器上(在iPhone 6模拟器或Android设备上没有看到相同的内容)”==>不对,只需等待一点TextInput
就会扩展。
There are nothing wrong with state and AsyncStorage. state和AsyncStorage没有任何问题。 I didn't get any warning. 我没有得到任何警告。
The root issue is the animation in FadeImage
: 根问题是FadeImage
的动画:
The app render many Carousel
, and each Carousel
has AngleInvestor
, and FadeImage
. 该应用程序渲染许多Carousel
,每个Carousel
都有AngleInvestor
和FadeImage
。 The problem is FadeImage
问题是FadeImage
FadeImage
run Animated
with duration 1000 => CPU is overloaded FadeImage
运行Animated
,持续时间为1000 => CPU过载
==> That why TextInput
add scroll then take a long time to expand, and FlatList
look like has problem, but not. ==>为什么TextInput
添加滚动然后需要很长时间才能展开,而FlatList
看起来有问题,但不是。 They are just slowly updated. 他们只是慢慢更新。
Solution: 解:
Try to comment FadeImage
, you will see the problem gone away. 尝试评论FadeImage
,你会发现问题消失了。
Don't start so many animations as the same time. 不要同时启动这么多动画。 Just start if it appears (Ex: the first card in Carousel
) 如果它出现就开始(例如: Carousel
的第一张卡片)
UPDATE UPDATE
I got your problem: typing fastly cause setState
call so many times . 我遇到了你的问题: 快速输入会导致setState
调用很多次 。 You use can debounce
for this situation: 你使用可以debounce
这种情况:
In App.js 在App.js中
render() {
console.log('render app.js')
...
<Section
id={item.id}
title={item.title}
pitch={item.pitch}
updatePitch={debounce(this.updatePitch, 1000)} // the key is here
questions={item.questions}
ready={this.state.ready}
/>
You can change the delay and watch the console log to see more. 您可以更改延迟并查看控制台日志以查看更多信息。 As I tried, delay about 500 can stop the warning. 我试过,延迟大约500可以停止警告。
P/s: You should try to remove forceUpdate
P / s:您应该尝试删除forceUpdate
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.