在React组件中渲染之前处理数据

时间:2019-03-07 20:31:21

标签: javascript reactjs

有了React的Angular背景,我无法在呈现数据之前就如何处理和重组数据投入了很多精力。 假设我将此对象从父组件传递给子组件:

{
    "_id": "5c716c53591610007f6d44ef",
    "model": {
        "_id": "5c7166eb591610007f6d44d4",
        "name": "E 300"
    },
    "serie": {
        "_id": "5c716ba0591610007f6d44e2",
        "name": "E-Class"
    }
},
{
    "_id": "5c716c60591610007f6d44f2",
    "model": {
        "_id": "5c7166f2591610007f6d44d6",
        "name": "E 220"
    },
    "serie": null
},
{
    "_id": "5c716c6a591610007f6d44f3",
    "model": {
        "_id": "5c7166fe591610007f6d44d8",
        "name": "C 180"
    },
    "serie": {
        "_id": "5c716ba4591610007f6d44e3",
        "name": "C-Class"
    }
},
{
    "_id": "5c716c6e591610007f6d44f4",
    "model": {
        "_id": "5c716702591610007f6d44d9",
        "name": "C 200"
    },
    "serie": {
        "_id": "5c716ba4591610007f6d44e3",
        "name": "C-Class"
    }
},
{
    "_id": "5c716c74591610007f6d44f5",
    "model": {
        "_id": "5c716705591610007f6d44da",
        "name": "C 220"
    },
    "serie": {
        "_id": "5c716ba4591610007f6d44e3",
        "name": "C-Class"
    }
}

我想将每个型号名称归类。 例如C-Class:['E300','E220']等,还将未定义序列的模型放入对象NoClass。

对于内联jsx来说太多了(至少看起来如此?),所以我需要一些辅助函数,但是我无法进行操作,因为每次我得到错误时,数据都未定义,这意味着它尝试在代码甚至还没有出现之前就对其进行渲染。

因此,我非常想将数据过滤到新对象中,然后渲染这些对象而不是原始道具数据。而且我不知道在渲染之前怎么做

我目前的内联尝试-它可以渲染,但是不会检查空系列对象,并且在哪里存在多个不同的序列时会中断:

class ModelSelect extends React.Component {
render() {
    const { models } = this.props
    return (
        models && <div className={"ModelSelect_Wrapper"}>
            <Select placeholder={"Model"} loading={models.loading} disabled={models.data.length === 0}>
                {_.uniqBy(models.data, 'name').map((serie) =>
                    <OptGroup label={serie.serie.name}>
                        {!models.loading && models.data.map((model, index) =>
                            <Option value={model.model._id} key={index}>{model.model.name}</Option>
                        )}
                    </OptGroup>
                )}

            </Select>
        </div>
    );
}

1 个答案:

答案 0 :(得分:0)

最简单的方法是使用商店。您有几个可用的选项,例如ReduxFluxMobx。不幸的是,学习使用商店有点困难。来自角度,我将把商店与来自angular.js 1x的$scope进行比较,不同之处在于没有魔术导致视图重新渲染,您必须依靠反应来检测道具的变化以便重新出现。这个想法是商店是一种数据结构,当对其进行修改时,将重新呈现将商店用作道具的组件。特别适用于异步获取数据的情况。

基本模式是

  1. 使用componentDidMount()将数据加载到高阶组件中
  2. 转换数据并使用新数据更新商店
  3. 您要将商店传递到<MyComponent store={store} />之类的组件
  4. 加载数据时,您将商店传递给子组件

以这种方式进行操作,您的组件可能看起来像

class MyComponent extends React.Component {
    static defaultProps = {
        store:{}
    }
    state = {
        loading: true
    }
    componentDidMount() {
        this.props.store.loadSomeData().then(()=>this.setState({loading:false}));
    }
    render(){
        return this.state.loading ? null : <MyChildComponent store={store} />
    }
}

请记住,您负责加载和转换商店中的数据,这只是组件如何显示加载和接收转换后的数据的概述。根据您所使用的商店,您的确切方法会大相径庭。

我的回答没有比这更具体的了,因为涉及的内容太多了,并且所需的工作范围在很大程度上取决于所使用的库。例如,mobx-3x要做的就是用@inject@observer装饰您的组件,它为您处理shouldComponentUpdate()的实现。

因此,您的第一步是选择一家商店,然后从那里去。祝你好运。