You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Redux Toolkit添加数据后返回页面报TypeError: property is not configurable问题排查

TypeError: property is not configurable 问题排查与解决

问题场景

使用Redux Toolkit创建userSlice,向cars数组添加条目后返回上一屏幕,触发如下错误:

TypeError: property is not configurable

This error is located at:
in VirtualizedList (created by FlatList)
...

相关代码

userSlice 代码

import { createSlice } from '@reduxjs/toolkit'

const initialStateVal = {
  cars: [],
}

const userSlice = createSlice({
  name: 'user',
  initialState: initialStateVal,
  reducers: {
    addNewCar: (state, action) => {
      state.cars.push(action.payload)
      //state.cars = [...state.cars, action.payload]
    },
    deleteCar: (state, action) => {
      state.cars = state.cars.filter((car) => car.license !== action.payload)
    },
  },
})

export const {
  addNewCar,
  deleteCar,
} = userSlice.actions

export default userSlice.reducer

添加条目调用代码

const addCar = () => {
    if (car.length > 0 && insurance.length > 0) {
      dispatch(
        addNewCar({
          license: car,
          insurance: insurance,
          traffic: trafficChecked,
          osaKaskochecked: osaKaskochecked,
          täysKaskochecked: täysKaskochecked,
        })
      )
      setCar('')
      setInsurance('')
      setValid(true)
      navigation.goBack()
      carAddedToast()
    } else {
      setValid(false)
    }
  }

FlatList 展示代码

const cars = useSelector((state) => state.user.cars)
{cars !== null ? <FlatList
            style={{ marginTop: 10 }}
            data={cars}
            keyExtractor={(item) => item.id}
            renderItem={({ item }) => {
              return (
                <View style={licenseContainer}>
                  <View
                    style={{
                      flexDirection: 'column',
                      justifyContent: 'center',
                      width: editCars ? '20%' : '25%',
                    }}
                  >
                    <Text
                      style={{
                        color: colors.white,
                        fontSize: 14,
                        textAlign: 'left',
                      }}
                    >
                      Rek.nro
                    </Text>
                    <Text key={item.license} style={carText}>
                      {item.license}
                    </Text>
                    <View style={horizontalDivider} />
                    <Text
                      style={{
                        color: colors.white,
                        fontSize: 14,
                        textAlign: 'left',
                      }}
                    >
                      Vakuutus
                    </Text>
                    <Text key={item.insurance} style={carText}>
                      {item.insurance}
                    </Text>
                  </View>
                  <View
                    style={{
                      flexDirection: 'column',
                      justifyContent: 'center',
                      width: editCars ? '24%' : '25%',
                    }}
                  >
                    <Text
                      style={{
                        color: colors.white,
                        fontSize: 14,
                        textAlign: 'center',
                      }}
                    >
                      Liikenne
                    </Text>
                    <CheckBox
                      center
                      key={item.traffic}
                      Component={TouchableWithoutFeedback}
                      size={30}
                      uncheckedColor={colors.white}
                      checkedColor={colors.red}
                      checked={item.traffic}
                    />
                  </View>
                  <View
                    style={{
                      flexDirection: 'column',
                      justifyContent: 'center',
                      width: editCars ? '24%' : '25%',
                    }}
                  >
                    <Text
                      style={{
                        color: colors.white,
                        fontSize: 14,
                        textAlign: 'center',
                      }}
                    >
                      Osakasko
                    </Text>
                    <CheckBox
                      center
                      key={item.osaKaskochecked}
                      Component={TouchableWithoutFeedback}
                      size={30}
                      uncheckedColor={colors.white}
                      checkedColor={colors.red}
                      checked={item.osaKaskochecked}
                    />
                  </View>
                  <View
                    style={{
                      flexDirection: 'column',
                      justifyContent: 'center',
                      width: editCars ? '24%' : '25%',
                    }}
                  >
                    <Text
                      style={{
                        color: colors.white,
                        fontSize: 14,
                        textAlign: 'center',
                      }}
                    >
                      Täyskasko
                    </Text>
                    <CheckBox
                      center
                      key={item.täysKaskochecked}
                      Component={TouchableWithoutFeedback}
                      size={30}
                      uncheckedColor={colors.white}
                      checkedColor={colors.red}
                      checked={item.täysKaskochecked}
                    />
                  </View>
                  {editCars ? (
                    <View
                      style={{
                        flexDirection: 'column',
                        justifyContent: 'center',
                        width: editCars ? '10%' : null,
                      }}
                    >
                      <Ionicons
                        name='ios-close-circle-outline'
                        size={30}
                        color={colors.black}
                        style={removeIcon}
                        onPress={() => removeCar(item.license)}
                      />
                    </View>
                  ) : null}
                </View>
              )
            }}
            ItemSeparatorComponent={() => {
              return <View style={divider} />
            }}
          /> : null}

用户已尝试的方案

  • 两种数组更新方式:state.cars.push(action.payload) 和 state.cars = [...state.cars, action.payload]
  • 添加空检查cars !== null
    均未解决问题。

问题原因

  1. FlatList keyExtractor 无效:设置了keyExtractor={(item) => item.id},但添加的每个car对象根本没有id属性,导致所有item的key都是undefined。FlatList依赖唯一key管理列表项渲染,无效key会引发内部DOM更新时的配置错误。
  2. 组件内key滥用:renderItem中给Text、CheckBox设置的key使用了布尔值(如item.traffic)或非唯一字符串(如item.license),React要求key必须是稳定且唯一的字符串/数字,重复或不稳定的key会导致React无法正确追踪组件变化,触发property is not configurable错误。

解决方案

1. 给每个car添加唯一id,修复keyExtractor

在添加car时生成唯一标识(比如时间戳),确保keyExtractor能获取有效key:

// 修改addCar中的dispatch参数
dispatch(
  addNewCar({
    id: Date.now().toString(), // 生成唯一id
    license: car,
    insurance: insurance,
    traffic: trafficChecked,
    osaKaskochecked: osaKaskochecked,
    täysKaskochecked: täysKaskochecked,
  })
)

此时keyExtractor={(item) => item.id}就能正常工作。

2. 移除或修正组件内的无效key

renderItem内部的Text、CheckBox不需要单独设置key(FlatList的key已经管理了父容器的唯一性),如果一定要加,必须用结合item.id的唯一值:

  • 错误示例:
<Text key={item.license} style={carText}>{item.license}</Text>
<CheckBox key={item.traffic} checked={item.traffic} />
  • 正确做法:移除这些key,或者改为:
<Text key={`${item.id}-license`} style={carText}>{item.license}</Text>
<CheckBox key={`${item.id}-traffic`} checked={item.traffic} />

3. 可选:规范Redux状态更新(非必要)

虽然RTK的Immer已经处理了不可变性,直接push没问题,但如果想更符合不可变更新规范,可以继续使用:

addNewCar: (state, action) => {
  state.cars = [...state.cars, action.payload]
}

这不是当前错误的根源,但能保持代码风格一致。


内容的提问来源于stack exchange,提问作者Jukka Koivu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 10:29:58