【发布时间】:2018-05-08 12:47:54
【问题描述】:
当我在键盘上打字时,我看到一些关于输入在 JS 代码之前的警告..
Native TextInput(react native 很棒)比 JS 提前 4 个事件 - 尝试让您的 JS 更快。
所以添加了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() {
...
顺便说一句:我现在正在做一些“道具钻探” - 但计划使用Context API (react 16.3)
警告似乎已经通过添加 debounce (1).. 但我看到了一些奇怪的问题 - 特别是在 iPhone 8 plus 模拟器上(在 iPhone 6 模拟器或 Android 设备上看不到相同的问题)
观察到的问题:
-
TextInput不要展开 - 它只是添加 scolling(在 iPhone 6 和 Android 设备上展开) -
FlatList中的一些布局问题 - 似乎无法找到正确的列表元素高度..
快速 JS 代码并同时保存到 state 和 AsyncStorage 的最佳做法是什么?
(1) 使用debounce 之外的另一种方法可能是使用getDerivedStateFromProps 并添加某种计时器,在一段时间后将状态推送到父组件。但不确定这是否会使JS代码更快。所以没试过。
更新(再次)
我开源了整个代码,因为当代码如此嵌套时,很难在 SO 帖子中提供所有需要的信息。
完整的代码在这里: https://github.com/Norfeldt/LionFood_FrontEnd
(我知道我的代码可能看起来很乱,但我仍在学习..)
我不希望人们进入并使用 PR 修复我的代码(即使它会很棒)但只是给我一些关于如何正确处理 state 和 AsyncStorage for TextInput 的代码指导.
我知道我有一些风格问题 - 很想解决它们,但也遵守 SO 并保持主题。
更新二
我删除了 forceUpdate 并将 FadeImage 替换为 vanilla react native Image。
但我仍然看到一些奇怪的问题
这是我的代码
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,
},
})
(我也更新了我的 git repo)
更新 III
我为state 和AsyncStorage 设置的设置似乎与debounce 配合得很好。我看到的问题是因为我正在耗尽 CPU(下一步要修复)。
【问题讨论】:
-
TextInput不需要去抖动。你为什么打电话给this.forceUpdate()?尝试删除它并去抖动。 -
@riwu 我强制更新它,因为我在使用 textinput 或 flatlist 时遇到了一些布局问题(不记得)
-
那么您应该尝试修复这些布局问题。在这里调用
this.forceUpdate()是绝对错误的。 -
您能否添加您的
data的结构?更好的数据结构可以带来更快的更新。 -
@bennygenel 我已经更新了我的问题
标签: javascript android ios reactjs react-native