映射并返回被视为对象的JSX

时间:2019-01-22 12:01:07

标签: javascript reactjs

我有一个包含其他对象的对象。这只是为了使每个条目都有一个ID,以便于引用。

我的帖子数据结构如下

{
    1: {
        id: 1,
        title: "test"
    },
    2: {
        id: 2,
        title: "qwerty"
    },
    3: {
        id: 3,
        title: "asdf"
    },
}

我正在使用lodash将这些项作为数组循环并返回JSX元素数组。但是,返回值被视为对象。

postsList() {
    return _.map(this.props.posts, post => {
        return (
            <a key={ post.id }>{ post.title }</a>
        );
    });
}

无论我如何处理转换,都会发生这种情况。我可以先将顶级对象转换为数组,然后将其映射,但是得到相同的结果。结果始终是一个对象。如果我在控制台日志中张贴该帖子,则它看起来如下

(3) [{...}, {...}, {...}]
0: {$$typeof: Symbol(react.element), type: "a", key: "1", ref: null, props: {…}, …}
1: {$$typeof: Symbol(react.element), type: "a", key: "2", ref: null, props: {…}, …}
2: {$$typeof: Symbol(react.element), type: "a", key: "3", ref: null, props: {…}, …}
length: 3
__proto__: Array(0)

当我尝试通过{this.postsList()}在组件中使用该函数时,出现错误Objects are not valid as a React child (found: object with keys {rendered}). If you meant to render a collection of children, use an array instead.

2 个答案:

答案 0 :(得分:1)

Lodash map方法返回一个数组,因此,通过返回地图,您实际上是在返回一个对象数组,因此为什么会出现上述错误。另外,放下Lodash地图,这是不需要的。

看看这个例子:https://jsfiddle.net/4x63fn9z/

const data = {
    1: {
        id: 1,
        title: "test"
    },
    2: {
        id: 2,
        title: "qwerty"
    },
    3: {
        id: 3,
        title: "asdf"
    },
}

class MyComponent extends React.Component {
    render() {
        return (
            <div>
                {Object.values(data).map(item => (
                    <div>{item.id}</div>
                 ))}
            </div>
        )
    }
}

ReactDOM.render(
  <MyComponent />,
  document.getElementById('container')
);

修复数据(您有重复的键)之后,我们可以使用Object.values()为我们提供对象数组,而不必依赖Lodash。从那里,我们可以使用本地.map()方法遍历该数组并返回适当的JSX。

答案 1 :(得分:0)

您的JSON对象不正确。您要多次重新定义键1,最后包含的唯一值是最后一个:{ id: 3, title: "asdf" }

const posts = {
    1: {
        id: 1,
        title: "test"
    },
    1: {
        id: 2,
        title: "qwerty"
    },
    1: {
        id: 3,
        title: "asdf"
    },
}

console.log(posts)

您有2个解决方案。

最简单的解决方案是将对象转换为以下数组并映射到其上:

工作示例:

const posts = [
    {
        id: 1,
        title: "test"
    },
    {
        id: 2,
        title: "qwerty"
    },
    {
        id: 3,
        title: "asdf"
    },
]

const App = props => <div>{posts.map(({ id, title }) => <a key={id}>{title}</a>)}</div>

ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
<div id='root'>

另一种方法是给每个元素一个不同的键并映射它们的值:

const posts = {
    1: {
        id: 1,
        title: "test"
    },
    2: {
        id: 2,
        title: "qwerty"
    },
    3: {
        id: 3,
        title: "asdf"
    },
}

const App = props => <div>{Object.values(posts).map(({ id, title }) => <a key={id}>{title}</a>)}</div>

ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.5.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.5.2/umd/react-dom.production.min.js"></script>
<div id='root'>

在任何情况下似乎都不需要Lodash