1

一个对象有一个引用一个或多个学校对象user的数组道具。schools我想使用<List>with<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)} />
}

如果在数组中引用 ,该checkSchool函数将返回布尔值。该函数从数组中添加或删除。school._iduser.schoolschangeSchoolschool._idusers.schools

changeSchool功能:

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

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

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

4

2 回答 2

1

假设您使用 UI Kitten,我可以看到您checked的组件的 prop 值错误CheckBox

UI Kitten CheckBox 参考

checked道具必须boolean不是可调用的,因为您在那里拥有它

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

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

让我知道这是否有帮助。

于 2020-05-01T19:54:39.320 回答
0

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

  • 使用@Cornel Raiu 提供的解决方案,已正确计算已选中和未选中的标志,但是在选中/未选中状态下显示不正确
  • 我用 Toggle 替换了 Checkbox,只是为了确保它也适用于 iOS
  • 我面临的问题仍然是,即使项目的状态被正确填充它正在被重置
  • Toggles 的外部容器是 List 和 ListItem,
  • 观察结果是 List 上的 Press 事件实际上是让 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}
                      />
    
于 2021-02-12T17:28:51.480 回答