Я пытаюсь отправить массив объектов, которые я получаю из MongoDB, клиенту (React.js) с помощью Node.js. Однако я продолжаю сталкиваться с ошибкой Objects are not valid as a React child (found: object with keys {_id, desc, price, purchased}), хотя уверен, что передал данные в правильном формате.
Как выглядит массив:
[{
desc:"Manage",
price: 5000,
purchased: false,
},
{
desc:"Deliver",
price: 2000,
purchased: false,
},
{
desc:"Market",
price: 4000,
purchased: false,
},
{
desc:"Agentone",
price: 8000,
purchased: false,
},
{
desc:"CPM",
price: 14000,
purchased: false,
},
{
desc:"Data",
price: 17000,
purchased: false,
},
{
desc:"E-Sign",
price: 9000,
purchased: false,
},
{
desc:"IGO",
price: 3000,
purchased: false,
},
{
desc:"DocFast",
price: 7000,
purchased: false,
}
],
Моя серверная сторона:
app.get('/item_info', (req, res) => {
var data;
MongoClient.connect(url, { useNewUrlParser: true }, function(err, db) {
if (err) throw err;
var dbo = db.db("ItemList");
dbo.collection("ItemInfo").find().toArray(function(err, result) {
if (err) throw err;
res.send({express: result})
db.close();
});
});
});
Мой клиент:
constructor(props){
super(props)
this.state = {
itemList:[]
}
}
componentDidMount() {
this.callApi()
.then(res => this.setState({itemList: res.express}))
.catch(err => console.info(err));
console.info(this.state.data)
}
callApi = async () => {
const response = await fetch('/item_info');
const body = await response.json();
if (response.status !== 200) throw Error(body.message);
return body;
};
render() {
return (
<div>
<div className = "App">
<header className = "App-header">
<img src = {logo} className = "App-logo" alt = "logo" />
<h1 className = "App-title">Welcome to Reactr</h1>
</header>
</div>
<div>{this.state.itemList[0]}</div>
</div>
)}
Чтобы убедиться, что клиент получает правильный формат, я распечатываю res.express на консоли, и он показывает следующее:
(9) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
0: {_id: "5bb223f5b717bc0aa0f5cf92", desc: "Manage", price: 5000, purchased: false}
1: {_id: "5bb223f5b717bc0aa0f5cf93", desc: "Deliver", price: 2000, purchased: false}
2: {_id: "5bb223f5b717bc0aa0f5cf94", desc: "Market", price: 4000, purchased: false}
3: {_id: "5bb223f5b717bc0aa0f5cf95", desc: "Agentone", price: 8000, purchased: false}
4: {_id: "5bb223f5b717bc0aa0f5cf96", desc: "CPM", price: 14000, purchased: false}
5: {_id: "5bb223f5b717bc0aa0f5cf97", desc: "Data", price: 17000, purchased: false}
6: {_id: "5bb223f5b717bc0aa0f5cf98", desc: "E-Sign", price: 9000, purchased: false}
7: {_id: "5bb223f5b717bc0aa0f5cf99", desc: "IGO", price: 3000, purchased: false}
8: {_id: "5bb223f5b717bc0aa0f5cf9a", desc: "DocFast", price: 7000, purchased: false}
length: 9
__proto__: Array(0)
Итак, клиент получает правильный формат массива. Я не могу понять, почему реакция кричит на меня
@MattKuhns Я получаю сообщение об ошибке: Objects are not valid as a React child (found: object with keys {_id, desc, price, purchased}
@MattKuhns также, когда я пытаюсь получить к нему доступ, выполнив {this.state.itemList[0].desc}, он говорит Cannot read property 0 of null, поэтому клиент не получает данные должным образом





Вы пытаетесь визуализировать объект напрямую. Как вы можете видеть, просмотрев полученную ошибку, сделать это невозможно. Итак, вам нужно отобразить свойства этого объекта.
render() {
return (
<div>
<div className = "App">
<header className = "App-header">
<img src = {logo} className = "App-logo" alt = "logo" />
<h1 className = "App-title">Welcome to Reactr</h1>
</header>
</div>
<p>{this.state.itemList[0].desc}</p>
<p>{this.state.itemList[0].price}</p>
// and so on
</div>
);
}
Конечно, вы не хотите визуализировать все объекты вручную. Итак, сначала используйте метод .map в своем массиве, а затем визуализируйте свойства.
class App extends React.Component {
state = {
itemList: [
{
_id: "1",
desc: "Manage",
price: 5000,
purchased: false
},
{
_id: "2",
desc: "Deliver",
price: 2000,
purchased: false
},
{
_id: "3",
desc: "Market",
price: 4000,
purchased: false
}
]
};
renderItems() {
return this.state.itemList.map(item => (
<div key = {item._id}>
<p>Desc: {item.desc}</p>
<p>Price: {item.price}</p>
{!item.purchased ? <p>Not purchased</p> : <p>Purchased</p>}
</div>
));
}
render() {
return <div>{this.renderItems()}</div>;
}
}
ReactDOM.render(<App />, document.getElementById("root"));<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id = "root"></div>this.state.itemList[0] возвращает ошибку Cannot read property '0' of null, поэтому настоящая проблема - это setstate, где itemList не получает данные должным образом.
И моя проблема в том, что если я делаю console.info (res.express), я действительно вижу данные, однако setstate просто не получает их
@SpencerOvetsky, это потому, что ваши данные поступают в результате асинхронной операции. В первом рендере нет itemList [0], поэтому вы не можете получить свойство из undefined. Вы пробовали мой код? Как отображение, а затем рендеринг элементов? Вы можете увидеть одно единственное свойство, подобное этому: { this.state.itemList[0] && this.state.itemList[0].desc } Но, опять же, большую часть времени вы хотите отобразить свои данные, а затем каким-то образом их визуализировать. Вы также можете снова выполнить условный рендеринг.
Я сделал. Это сработало. Есть ли работа, кроме использования карты? Поскольку мне нужно использовать эти данные в дочернем компоненте и отдельно изменять отдельный дочерний компонент (другой стиль). Работает ли использование axios?
В какой-то момент вам придется использовать .map. Наличие дочернего компонента не влияет на это, вместо прямого рендеринга просто передайте item дочернему компоненту и делайте там все, что захотите. axios или любой другой метод выборки не имеет отношения к вашей проблеме. Ваши данные поступают после первого рендеринга, поэтому вам следует выполнить условный рендеринг, если у вас есть проблемы с этим.
потому что мне нужно заключить все три моих дочерних компонента в строку и каждый дочерний компонент в столбец. и я, кажется, не могу понять это только с помощью карты. потому что внутри функции карты вы должны вернуть полный div, однако, если я хочу обернуть их в строку. Первый компонент будет иметь открывающий тег <div className = "row">, а третий дочерний компонент будет иметь </div>, поскольку они возвращают только часть тега div, это считается недопустимым синтаксисом.
Я не могу представить себе всю ситуацию прямо сейчас. Вы можете использовать React.Fragment вместо div везде, где вашему JSX нужна оболочка. Если проблема с этим вопросом решена для вас, примите мой ответ, задайте новый вопрос и опишите все подробности.
Добро пожаловать. Просто попробуйте написать код, и если вы столкнетесь с проблемой, не стесняйтесь задавать вопрос.
Можете показать, как реагируют на вас "крики"?