【问题标题】:React Native: Checkbox List StructureReact Native:复选框列表结构
【发布时间】:2020-05-01 19:31:22
【问题描述】:

user 对象有一个数组属性 schools 引用一个或多个学校对象。我想使用 <List><CheckBox> 来改变 schools 数组。

我将user 对象加载到视图中,并加载listOfSchools(从应用程序状态)以生成复选框列表:

<List data={listOfSchools} keyExtractor={ item=> item._id } renderItem={({item})=>renderItem(item)} />

renderItem 函数:

const renderItem = (school) => {

    return <ListItem
        title={school.name}
        accessory={()=>renderAccessory(school)}
    />
};

renderAccessory 函数:

const renderAccessory = (school) => {
    return <CheckBox checked={() => checkSchool(school._id)} onChange={()=>changeSchool(school._id)} />
}

如果school._iduser.schools 数组中被引用,checkSchool 函数将返回布尔值。 changeSchool 函数在users.schools 数组中添加或删除school._id

changeSchool 函数:

const changeSchool = (schoolId) => {
    let checked = checkSchool(schoolId);
    if (!checked) {
        // add schoolId to user.schools
    } else {
        // remove schoolId from user.schools
    }
}

这根本行不通。看来,无论我使用什么来改变状态,复选框都不会更新,user.schools 数组也不会改变。

构建这样一个设计目标的正确方法是什么?

【问题讨论】:

  • 我假设你使用 React Native Elements。如果是这种情况,checked 需要是 boolean
  • 澄清一下,我正在使用 ui-kitten,这似乎几乎相同。 onChange 是一个可用的道具。 @CornelRaiu,checkSchool 返回一个布尔值。这可以接受吗?
  • 我明白了。那我去看看
  • 现在可以了吗?我目前只是在更新我的答案
  • 看来这是主要问题,是的。如果你发布你的答案,我会接受它

标签: react-native react-native-ui-kitten


【解决方案1】:

假设您使用 UI Kitten,我可以看到您为 CheckBox 组件设置了错误的 checked 属性值。

UI Kitten CheckBox reference

checked 属性必须是 boolean 而不是 Callable,因为你有它

我会尝试像这样更改代码:

const renderAccessory = (school) => {
    const isChecked = checkSchool(school._id);
    return <CheckBox checked={isChecked} onChange={()=>changeSchool(school._id)} />
}

如果有帮助,请告诉我。

【讨论】:

    【解决方案2】:

    在尝试各种解决方案时,我可以在这里总结出几件事:

    • 使用@Cornel Raiu 提供的解决方案,已正确计算已选中和未选中的标志,但是显示不正确,处于选中/未选中状态
    • 我用 Toggle 替换了 Checkbox,只是为了确保它也适用于 iOS
    • 我面临的问题仍然是,即使项目的状态被切换是正确填充它正在被重置
    • Toggles 的外部容器是 List 和 ListItem,
    • 观察是 List 上的 Press 事件实际上是让 Checkbox/Toggle 进入正确的显示状态...

    解决方案: 经过较长时间的研究和实验后,我开始使用以下方法 -

    • 我维护了已检查项目的单独集合

    • 已经有一个主条目集合的状态,作为列表的输入

    • 每次单击 Checkbox/Toggle 时,都会克隆数据的主列表并复制回其状态

    • 这触发了组件的轻微重新渲染,事情按预期工作。

        const [cashTransactions, setCashTransactions] = useState([]); // master data
        const [selectedTransactions, setSelectedTransactions] = useState([]); // selected data
        const renderItem = ({ item, index }) => (
                <ListItem
                  title={'('+item.id + ') ' + item.firstName + ' ' + item.lastName}
                  description={Moment(item.createdOn).format('yyyy-MM-DD hh:mm:ss')}
                  accessoryLeft={selectedTransactions.includes(item.id) ? RadioOnIcon : RadioOffIcon}
                  accessoryRight={() => checkBoxSpace(item)}
                />
              );
      
      
              const checkBoxSpace = (item) => {
                let itemChecked = selectedTransactions.includes(item.id);
                return (
                  <View style={styles.actionContainer}>
                    <Button size='tiny' status='basic' accessoryLeft={rupeeSymbol}>{item.amount}</Button>
                    <Toggle checked={itemChecked} status='primary' size='small' onChange={checked => checkboxChecked(item, checked)}></Toggle>
                  </View>
                )
              }
      
      
              const checkboxChecked = (item, checked) => {
                console.log('Item -' + item.id + ' ' + checked);
                if (checked) {
                  if (!selectedTransactions.includes(item.id)) {
                    selectedTransactions.push(item.id);
                  }
                } else {
                  if (selectedTransactions.includes(item.id)) {
                    selectedTransactions.pop(item.id);
                  }
                }
                console.log('selectedTransactions ' + JSON.stringify(selectedTransactions));
                // This is the thing i applied to get it done.
                const cloned = [...cashTransactions];
                setCashTransactions(cloned);
              }
      
                     // View
                      <List
                          style={styles.container}
                          data={cashTransactions}
                          renderItem={renderItem}
                        />
      

    【讨论】:

    • 我用过 UI-Kitten 库
    猜你喜欢
    • 1970-01-01
    • 2021-06-27
    • 1970-01-01
    • 2022-11-21
    • 1970-01-01
    • 1970-01-01
    • 2022-09-29
    • 2018-08-28
    • 1970-01-01
    相关资源
    最近更新 更多