具有多个输入的状态管理(列表)

时间:2017-07-26 03:26:49

标签: react-native

我试图找出管理状态的最佳位置,以反应本地输入列表,但没有找到任何好的,彻底的例子或明确的指导,我可以看到一些选项。

为简单起见,不包括有关管理状态的工具的详细信息,因为我的理解是状态的存储方式不会影响其管理的组件。

方案

一个屏幕组件,它接收一组项目作为要在ListItem列表中显示的道具。每个ListItem都包含一个输入,为简单起见,想象一个开关(布尔值)。

用例包括一系列表单问题或设置,以便在列表中显示并允许用户输入。伪代码:

class SettingsView extends Component {
  render () {
    return (
      <View>
        <List style={styles.list}>
          {this.props.inputArray.map((item, index) => (
            <ListItem
              title={item.title}
              isSwitched={item.value}
              key={index}
              onSwitchChange = {this.onChange}
            />
          ))}
        </List>
      </View>
    );
  }
}

选项1 基于Thinking in React页面,我想到的一个选项是通过在SettingsView构造函数状态中创建(inputArray).length数组并在onChange函数更新该数组的基础上在屏幕(SettingsView)级别管理状态关键。

选项2 我看到的第二个选项是让每个ListItem管理它显示的状态。从封装角度来看,这对我有意义,但是对于状态的管理则更少,因为onSwitchChange函数在SettingsView中,并且我不清楚它是如何工作的。

我还有其他选择吗?承认React / RN的经验是有限的,而def来自像iOS的列表数据源模型这样的更为客观的思维模式。

注意:另一种选择是让整个inputArray处于状态,而不是作为道具传递。我的理解是应该最小化状态,因此设计只有inputArray中每个项目的输入应该处于该状态。即表格标签(即问题)是非道具的道具。

1 个答案:

答案 0 :(得分:1)

选项1 将是更好的选择,有这个概念“智能组件和哑组件”

智能组件:通常保存与其关联的所有子组件的状态,它还定义传递给子组件以修改其状态的函数。

哑组件:这些组件接收包含数据和函数的道具,它们通常没有自己的状态,并且在很大程度上依赖于父组件。

问题在于,当你创建一个组件时,你需要决定它是聪明的还是愚蠢的,通常我将一个屏幕关联到一个智能组件,在你的例子中,它将是SettingsView(智能),它将保持状态和功能孩子将是愚蠢的组件,但这实际上是特定于应用程序的决定,因为你可能有一个基于上下文动态的SettingsView,所以让它成为一个愚蠢的组件会更好,让我们使用上面的例子

由于“设置视图”依赖于从父级传递的this.props.inputArray 我无法修改的组件(我将称之为ParentComponent) inputArray直接在SettingsView中你可以做的是传递另一个道具 ParentComponent到SettingsView,它是一个修改inputArray的函数

class ParentComponent extends Component {
    constructor(props) {
        super(props);
        this.state = {
            inputArray: [],
        };
        this.onSwitchChange = this.onSwitchChange.bind(this); // when passing fn
    }
    onSwitchChange(index) { // index will come from the child component
        // do some logic here based on the index then update the state
        this.setState('inputArray' updatedState); // updatedState is just an example variable
    }
    render() {
        return (
            <View>
                <SettingsView 
                    onSwitchChange={(index) => () => this.onSwitchChange(index)}
                    inputArray={this.state.inputArray} 
                />
            </View>
        );
    }
    /*
        (index) => () => this.onSwitchChange(index)
        this is a function that will return another function
        we need this because we want to delay the execution of onSwitchChange
        and capture index and associate it with that method, typically this
        is used if were passing function to child component(SettingsView) which will be used as
        a handler for events.
    */
}

class SettingsView extends Component {
  render () {
    return (
      <View>
        <List style={styles.list}>
          {this.props.inputArray.map((item, index) => (
            <ListItem
              title={item.title}
              isSwitched={item.value}
              key={index}
              onSwitchChange={this.props.onSwitchChange}
            />
          ))}
        </List>
      </View>
    );
  }
}

此示例可能毫无意义,因为您可以使用SettingsView作为ListItem和其他组件的父级,但由于SettingsView状态现在由ParentComponent管理,因此它现在是一个愚蠢的组件,可用于具有特定状态的其他屏幕SettingsView需要运行。一般的目标是创建尽可能多的哑组件,原因是这些类型的组件是高度可重用的,因为你只需要将它们传递给正确的工作。