react-native - 如何在 React Native 中重置子组件中的计数器
问题描述
我有一个 PlusMinus 组件,其目的是让用户增加或减少一个整数。在我的父组件中,我遍历列表中的几个项目并为每个项目提供一个 PlusMinus 计数器。
如何重置父组件中的所有计数器?此类问题的大多数答案都建议在父级中处理状态,使子级无状态,并通过道具将值传递给子级。但是,当我在父项中更新这些道具值时,子项不会更新。一些答案组件WillReceiveProps。但是,该功能已被弃用,无论如何我都无法让它工作。
这是我的组件。它有效,但我无法重置计数器。如何在我的父母中提供一个重置所有子计数器的按钮?
import * as React from 'react'
import { Text, TouchableOpacity, View } from 'react-native'
import styles from './Styles'
type Props = { k: string, handler: Function, style: Object }
type State = { clicks: Object }
export default class PlusMinus extends React.Component<Props, State> {
state = {
clicks: {}
}
IncrementItem = (k: string) => {
let clicks = this.state.clicks
if ('undefined' == typeof this.state.clicks[k]) {
clicks[k] = 1
}
else {
clicks[k]++
}
// A handler passed from the parent that updates persistent values in the parent.
this.props.handler(k, clicks[k])
this.setState(
{ clicks: clicks }
)
}
DecreaseItem = (k: string) => {
let clicks = this.state.clicks
if ('undefined' == typeof this.state.clicks[k]) {
clicks[k] = 0
}
else if (this.state.clicks[k] > 0) {
clicks[k]--
}
this.props.handler(k, clicks[k])
this.setState(
{ clicks: clicks }
)
}
Count = (k: string) => {
let ct = 0
if ('undefined' !== typeof this.state.clicks[k]) {
ct = this.state.clicks[k]
ct = ct++
}
return (
<Text style={styles.counter} id={k}>{ ct }</Text>
)
}
render() {
return (
<View style={this.props.style}>
<TouchableOpacity style={styles.plusminus} title='+' onPress={() => this.IncrementItem(this.props.k)}>
<Text style={styles.pmtxt}>+</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.plusminus} title='-' onPress={() => this.DecreaseItem(this.props.k)}>
<Text style={styles.pmtxt}>-</Text>
</TouchableOpacity>
<View style={[{
paddingHorizontal: 10,
marginLeft: 4,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#aaa',
width: 40,
borderRadius: 5
}]}>{this.Count(this.props.k)}</View>
</View>
)
}
}
我在父组件中的处理程序看起来像......
handler = async (key: string, value: Number) => {
let object = {}
let str = await Expo.SecureStore.getItemAsync('clicks')
if (str) {
object = JSON.parse(str)
}
object[key] = value
str = JSON.stringify(object)
Expo.SecureStore.setItemAsync('clicks', str)
}
-------- 更新:这是一个工作示例。--------
import * as React from 'react'
import { Text, TouchableOpacity, View } from 'react-native'
import styles from './Styles'
type Props = { k: string, handler: Function, style: Object, clicks: Number }
export default class PlusMinus extends React.Component<Props> {
IncrementItem = (k: string) => {
let clicks = this.props.clicks
this.props.handler(k, clicks, '++')
}
DecreaseItem = (k: string) => {
let clicks = this.props.clicks
this.props.handler(k, clicks, '--')
}
Count = (k: string) => {
let ct = 0
if ('undefined' !== typeof this.props.clicks) {
ct = this.props.clicks
}
return (
<Text style={styles.counter} id={k}>{ ct }</Text>
)
}
render() {
return (
<View style={this.props.style}>
<TouchableOpacity style={styles.plusminus} title='+' onPress={() => this.IncrementItem(this.props.k)}>
<Text style={styles.pmtxt}>+</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.plusminus} title='-' onPress={() => this.DecreaseItem(this.props.k)}>
<Text style={styles.pmtxt}>-</Text>
</TouchableOpacity>
<View style={[{
paddingHorizontal: 10,
marginLeft: 4,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#aaa',
width: 40,
borderRadius: 5
}]}>{this.Count(this.props.k)}</View>
</View>
)
}
}
以及父组件的工作处理程序......
handler = async (key: string, value: Number, pm: string) => {
let ct = 1
let n = this.state.clicks[key]
if ('++' == pm) {
ct = n
ct++
}
else {
ct = 0
if (n > 0) {
ct = n
ct--
}
}
let clicks = this.state.clicks
clicks[key] = ct
this.setState({clicks: clicks})
}
以及父渲染中子组件的 JSX...
<PlusMinus k={k} clicks={this.state.clicks[k]} style={{
flexWrap: 'wrap',
flexDirection: 'row',
marginBottom: 0,
marginRight: 12,
paddingBottom: 0,
paddingRight: 5,
paddingLeft: 5
}} handler={this.handler} />
解决方案
我相信最好的方法正是您所描述的:您的父组件应该处理点击并将其作为道具传递给子组件,其中点击数来自状态,例如:
state = { clicks: [] }
...
<PlusMinus clicks={this.state.clicks[i]} />
然后,当您想要重置点击时,您只需在 this.state.clicks 上运行一个循环并将所有项目设置为 0(显然,通过使用新数组调用 setState)。当然,子组件可以是无状态的,并且递增/递减函数应该移动到父组件。