首页 > 解决方案 > 从许多相同的子组件中检索状态值反应原生

问题描述

我有一个包含许多相同CustomSlider组件的屏幕。我想从每个滑块中检索滑块值。

在本机反应中这样做的最佳实践是什么?

这是一个最小的工作示例,带有 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>
    );
  }
}

标签: react-nativeexpo

解决方案


不需要复杂的解决方案。我处理这个问题的方法是管理父组件中的状态。TheCustomSlider并不真的需要知道它的状态。由于父组件需要知道滑块的状态,所以最好在那里处理它。

因此,由于父组件将处理状态,这意味着我们需要对您正在做的事情进行一些更改。

  1. 在父组件中为每个滑块的状态设置初始值。这很重要,这意味着即使用户没有触摸滑块,我们也知道它们的值。
  2. 将函数传递给回调父组件的每个滑块。
  3. 由于父组件控制状态,我们可以从CustomSlider. 这提供了一些选项,我们可以将其保留为 a Component,将其更改为 aPureComponent或更进一步将其更改为 aFunctional 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需要知道它的状态,因为它所做的不仅仅是捕获滑块的值,那么您可以通过将其用作 aComponent或 a来轻松地为其添加状态PureComponent


小吃

这是显示上述代码工作的小吃。我已经展示了所有三个可能的组件,并在App.js. 它们的外观没有太大区别,但您的用例将决定您使用哪一个。https://snack.expo.io/@andypandy/multisliders


最佳实践

最佳做法是寻找您能找到的最简单的解决方案。理想情况下,这将是 a Functional Component,然后是 a PureComponent,最后是 a Component。考虑将在何处以及如何使用状态也很重要。我问自己的一些问题是:

  • 组件真的需要知道自己的状态吗?
  • 我打算在哪里使用该状态?
  • 我需要这些状态值多久?
  • 我需要保持这种状态吗?
  • 根据我目前使用的工具,我可以使用哪些工具?
  • 我真的需要添加另一个或更多依赖项来完成这项工作吗?

如果您需要应用程序中多个位置的滑块值,您可以使用react-native导航提供的一些功能来传递这些值。Redux 和 MobX 在复杂性方面开销很大,只有在需要全局状态管理系统时才应该真正使用,在大多数情况下可以避免它们。


推荐阅读