修改state时报错 You attempted to set the key 'active' with the value 'false' on an object ..



  • 像做如下功能,一堆checkbox,选中某个,把结果保存到AsyncStorage并更新到state里面。现在点击报错
    "You attempted to set the key 'active' with the value 'false' on an object that is meant to be immutable and has been frozen"

    const AsyncStorageKey = '_AS'
    
    export default class MyPage extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          langItems: []
        }
      }
    
      componentWillMount() {
       // 获取列表 [{}, {}, {}, {}]
        langList().then(res => {
          console.log(res)
          this.state.langItems = res
        })
      }
    
      renderCheckBoxes () {
        return this.state.langItems.map((item, index) => {
          return (
            <View>
              <Text>{item.name}</Text>
              <CheckBox onValueChange={() => this.onChangeCheckbox(item)} value={item.checked}/>
            </View>
          )
        })
      }
    
      onChangeCheckbox (item) {
        // 找到所选的checkbox item并更新到state
        let langItems = this.state.langItems.slice(0);
    
        for (let i=0; i < langItems.length; i++) {
          if (langItems[i].name === item.name){
            langItems[i].checked = !langItems[i].checked
          }
        }
    
        AsyncStorage.setItem(AsyncStorageKey, langItems, ()=>{
          this.setState({
            langItems: langItems
          })
        });
    
        ToastAndroid.show(`${item.name}`, ToastAndroid.SHORT)
      }
    
      render() {
        const navigation = this.props.navigation;
        return (
          <ScrollView style={{flex: 1}}>
            <View>
              <Text onPress={() => { navigation.navigate('customKey') }}>my page</Text>
              {this.renderCheckBoxes()}
            </View>
          </ScrollView>
        )
      }
    }
    


  • 报的错误意思是:你设置的对象是不可变的,已经被冻结

    初步猜测是AsyncStorage在存储时将langItems对象冻结了,但最关键的是你的用法不对,因为AsyncStorage的第二个参数是一个string。

    见AsyncStorage文档中的说明: static setItem(key: string, value: string, callback?: ?(error: ?Error) => void)

    如果非要存储的话,那也需要JSON.stringify一下,转成字符串存进去。将来取值时还要转成对象。个人建议如果app运行期需要持久化一个对象的话,用redux或者mobx,如果是永久持久化,那么就用数据库吧,刚进来就ajax拉一下数据。


  • administrators

    更重要的问题是,state不能直接赋值修改,必须通过setState修改


登录后回复