我有一个包含许多相同CustomSlider
组件的屏幕。我想从每个滑块中检索滑块值。
在React Native中这样做的最佳实践是什么?
这是一个最低的工作示例,有3个滑块:
import React, { Component } from 'react';
import { View, Text } from 'react-native';
import MultiSlider from "@ptomasroos/react-native-multi-slider";
class CustomSlider extends Component {
constructor(props) {
super(props)
this.state = {
multiSliderValue: [1, 9]
}
}
multiSliderValuesChange = values => {
this.setState({multiSliderValue: values});
};
render(){
return (
<MultiSlider
values={this.state.multiSliderValue}
onValuesChange={this.multiSliderValuesChange}
min={0}
max={10}
step={1}
/>
)
}
}
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
};
}
get_slider_values = () => {
// what is best practice to access the values of every slider here?
// eg an object like this
const slider_values = [[1.4, 7.4], [4.3, 7.0], [1.9, 3.2]]
return slider_values
}
render() {
return (
<View style={{alignItems: 'center', justifyContent: 'center', padding: 50}}>
<CustomSlider />
<CustomSlider />
<CustomSlider />
<Text>{`The slider values are: ` + JSON.stringify(this.get_slider_values())}</Text>
</View>
);
}
}
不需要复杂的解决方案。我处理的方式是管理父组件中的状态。CustomSlider
确实不需要知道其状态。由于父组件需要知道滑块的状态,因此最好在那里处理它。
因此,由于父组件要处理状态,这意味着我们需要对您正在做的事情进行一些更改。
- 在每个滑块状态的母体组件中设置初始值。这很重要,这意味着即使用户不触摸滑块,我们知道它们的值。
- 将功能传递给每个滑块,以回电给父部件。
- 作为父组件控制状态,我们可以从
CustomSlider
删除状态。这给出了一些选项,我们可以将其保留为Component
,将其更改为PureComponent
或向更改为Functional Component
,如果滑块真的不需要知道其状态,那么最后一个选项应该最适合性能。
这是我将如何重构您的App.js
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
sliderValues: [[1, 9],[1, 9],[1, 9]] // we should control the state here
};
}
// this uses function currying to bind the function and pass a value to it
onChange = (index) => (values) => {
this.setState( prevState => {
let sliderValues = prevState.sliderValues;
sliderValues[index] = values;
return {
sliderValues
}
})
}
render() {
return (
<View style={{alignItems: 'center', justifyContent: 'center', padding: 50}}>
<CustomSlider intialValues={this.state.sliderValues[0]} onChange={this.onChange(0)}/>
<CustomSlider intialValues={this.state.sliderValues[1]} onChange={this.onChange(1)}/>
<CustomSlider intialValues={this.state.sliderValues[2]} onChange={this.onChange(2)}/>
<Text>{`The slider values are: ` + JSON.stringify(this.state.sliderValues)}</Text>
</View>
);
}
}
请注意,我们实际上不需要一个函数来获取滑块的值,因为它们存储在状态下。这意味着我们可以使用this.state.sliderValues
直接访问滑块的值。
这是您的CustomComponent
重构以使用上述代码:
class CustomSlider extends Component { // this could easily be swapped for a PureComponent
render(){
return (
<MultiSlider
values={this.props.intialValues}
onValuesChange={this.props.onChange}
min={0}
max={10}
step={1}
/>
)
}
请注意,当父组件正在处理它时,它根本不需要管理状态。这也意味着我们可以删除很多实际上不需要的代码。这就是为什么我认为我们可以进一步迈出一步并将其成为Functional Component
const CustomSlider = ({intialValues, onChange}) => {
return (
<MultiSlider
values={intialValues}
onValuesChange={onChange}
min={0}
max={10}
step={1}
/>
)
}
但是,如果CustomSlider
需要知道其状态,因为它做的不仅仅是捕获滑块的值,则可以通过将其用作Component
或PureComponent
轻松添加状态。
小吃
这是一个零食,显示上述代码工作。我已经显示了所有三个可能的组件,并在App.js
中使用了它们。它们的外观没有太大的差异,但是您的用例将确定您使用的哪一个。https://snack.expo.io/@andypandy/multisliders
最佳实践
最好的做法是获得您可以找到的最简单解决方案。理想情况下,这将是Functional Component
,然后是PureComponent
,最后是Component
。考虑国家将在哪里以及如何使用国家也很重要。我问自己的一些问题是:
- 组件真的需要知道自己的状态吗?
- 我打算在哪里使用该状态?
- 我需要多长时间?
- 我需要坚持这个状态吗?
- 根据我当前正在使用的东西,我可以使用哪些工具?
- 我真的需要添加另一个依赖或更多以使这项工作吗?
如果您需要应用程序中多个位置的滑块值,则可以使用react-native
提供的某些功能或导航来传递这些值。Redux和MOBX在复杂性方面是很大的间接费用,只有在需要全球状态管理系统的情况下,就可以真正使用,在大多数情况下可以避免它们。
您可以通过给出每个孩子的某些键动态存储状态,并通过您给它的键访问每个状态。
一种方法是将闭合从父组件传递到 CustomSlider
s作为props并监视更改。
<CustomSlider idx={n}
theClosurePassedThrough= (n, values) => {
// update the parents states here accordingly
}
>
然后在适当的时间调用此关闭。
multiSliderValuesChange = values => {
this.setState({multiSliderValue: values});
this.props.theClosurePassedThrough(this.props.idx, values);
};
最好的做法是使用mobx或redux。