首页 > 解决方案 > 在 React 组件中渲染之前操作数据

问题描述

有了 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 来说太多了(至少看起来如此 ??)所以我需要一些辅助函数,但我无法进行操作,因为每次我收到数据未定义的错误,这意味着它会尝试渲染在它出现并被修改之前的代码。

所以我非常想将数据过滤成新的对象,然后渲染这些而不是原始的道具数据。而且在渲染之前我不知道该怎么做

我目前内联的尝试 - 它确实呈现但它不检查空系列对象并在超过 1 个不同系列时中断:

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>
    );
}

标签: javascriptreactjs

解决方案


最简单的方法是使用商店。您有几个可用的选项,例如ReduxFluxMobx。不幸的是,学习使用 Stores 有点困难。来自 angular,我会将商店$scope与 angular.js 1x 进行比较,不同之处在于没有魔法导致视图重新渲染,您必须依靠反应检测道具的变化才能发生重新渲染。这个想法是 store 是一个数据结构,当它被修改时,使用 store 作为 prop 的组件将被重新渲染。这非常有用,尤其是在您异步获取数据时。

基本模式是

  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()实现。

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


推荐阅读