【问题标题】:React component does not react to mobx observable dataReact 组件不对 mobx 可观察数据做出反应
【发布时间】:2018-01-22 16:35:15
【问题描述】:

我在我的 react native 项目中使用 mobX。请考虑这个商店类:

class Birds {
    @observable listOne = [];
    @observable fetchingListOne = false;
    @observable fetchErrorOne = '';

    @action setListOne = () => {
        this.fetchingListOne = true;
        api.getList()
            .then((data) => {
                this.listOne.replace(data);
                this.fetchingListOne = false;
            })
            .catch((error) => {
                this.fetchingListOne = false;
                this.fetchErrorOne = error;
            });
    };
}

这是反应组件:

@inject('BirdStore') @observer
export default class Flat extends React.Component {
    componentDidMount() {
        this.props.BirdStore.setListOne();
    }

    _renderHeader = () => {
        return <Text style={styles.listHeaderText}>
            Hello {this.props.BirdStore.listOne.length} is {this.props.BirdStore.fetchingListOne.toString()}
            </Text>;
    };

    _renderItem = ({item}) => {
        return <Text style={styles.item}>{item.name}</Text>
    };

    _renderFooter = () => {
        if (this.props.BirdStore.fetchingListOne) {
            return <ActivityIndicator/>
        }
        else {
            return null
        }
    };

    render() {
        const dataSource = this.props.BirdStore.listOne.slice();

        return (
                <View style={styles.container}>
                    <Text>Fetching: {this.props.BirdStore.fetchingListOne.toString()}</Text>
                    <FlatList
                        style={styles.listContainer}
                        ListHeaderComponent={this._renderHeader}
                        data={dataSource}
                        renderItem={this._renderItem}
                        keyExtractor={(item, i) => item.id}
                        ListFooterComponent={this._renderFooter}
                    />
                </View>
        )
    }
}

在我看来,从上面看:

  1. Flat组件挂载时,调用storesetListOne()的方法。
  2. setListOne()fetchingListOne 设置为 true 并进行 api 调用。
  3. 在组件端,当fetchingListOne为真时,ActivityIndi​​cator显示,而在ListHeaderComponent中它应该显示为真。
  4. 在商店端,响应成功/不成功后,将fetchingListOne设置为false。
  5. 最后在组件方面,因为fetchingListOne设置为false,ActivityIndi​​cator不应该显示,而在ListHeaderComponent中应该显示为false。

但是,事实并非如此。这里当调用setListOne() 方法时,将fetchingListOne 设置为true 后,组件不会对api 调用后所做的更改做出反应。 ActivityIndi​​cator 不断显示,在 ListHeaderComponent 中显示为 true。

我在这里做错了什么?请你帮助我好吗。谢谢

更新

我在 FlatList 之前添加了一个 Text 组件。在组件类的 render 方法中添加 Text 组件或控制台日志记录确实会使 FlatList 对更改做出反应。不过我不知道为什么会这样。

【问题讨论】:

  • 您可以尝试使用mobx.useStrict() 看看它是否能解决您的问题吗?这意味着为您的可观察值使用 getter 和 setter,尤其是 fetchingListOne
  • @ChristopherChiche 我尝试将mobx.useStrict(true) 放在 Birds 类所在的 store.js 中。但这给了我一个错误:...如果打算进行此更改,请将代码包装在action 中。尝试修改:Birds@2.listOne]。所以我把useStrict();放在@action setListOne中。它不会抛出任何错误,但它有同样的问题; FlatList 组件不会对这些更改做出应有的反应。

标签: reactjs react-native mobx mobx-react


【解决方案1】:

您在这里最可能遇到的问题是,虽然Flatobserver 组件,但FlatList 不是(毕竟它是一个内置组件)。在此设置中,_renderFooter 和其他部分由FlatListrender 渲染,但不是FlatList 的渲染。因此,它们不是 Flat 生命周期的一部分,而是 FlatList 生命周期的一部分,因此 Mobx 不会跟踪它们

有两种方法可以解决这个问题,都很简单:

1) 将_renderItem 声明为观察者组件:

_renderItem = observer(({item}) =>
    <Text style={styles.item}>{item.name}</Text>
);

2) 使用内联匿名Observer 组件:

_renderItem = ({item}) => 
    <Observer>{
        () => <Text style={styles.item}>{item.name}</Text>}
    </Observer>

【讨论】:

  • 是的,我认为这就是问题所在,因为我在 FlatList 上方添加了一个 Text 组件,它确实会对更改做出反应,另外,这使得整个 FlatList 完美运行(更新代码请查看 Class 的 render 方法)。无论如何,第一种方法会报错,[TypeError: Cannot call a class as a function]。第二种方法基本上做同样的事情;它会在获取后呈现所有列表。
猜你喜欢
  • 2018-07-28
  • 1970-01-01
  • 1970-01-01
  • 2020-08-24
  • 1970-01-01
  • 1970-01-01
  • 2020-12-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多