У меня есть файл JSON со структурой типа "data.json"
{
"Object1": {
"name": "1",
"rank": "2"
},
"Object2": {
"name": "3",
"rank": "4"
}
}
и в моем коде React у меня есть данные для установки моего состояния реакции. Я хочу передать Object2 другому компоненту, но не могу различать данные.
// import packages
import React, { Component } from "react";
import io from 'socket.io-client';
class App extends Component {
constructor() {
super();
this.state = {
data: null
};
this.socket = io('http://localhost:5000');
// Binders
this.updateState = this.updateState.bind(this);
}
componentDidMount() {
this.socket.on('send data', this.updateState);
}
updateState(result) {
this.setState({
data: result
});
}
render() {
return (
<p style = {{ textAlign: "center" }}>
{this.state.data}
</p>
);
}
}
export default App;
Когда я пытаюсь сослаться на что-то вроде this.state.data или this.state.data.Object1.name, он указывает на нулевой объект. Что я делаю не так?
@devserkan, я вижу данные на моей пустой домашней странице и консоли. Почему this.state.data не работает? Это работает, но не так, как я пытаюсь заставить его работать. Я пропускаю все через сокет, чтобы полностью обновить приложение за один раз.
это потому, что это не Object1, а Object11?
@azium это просто опечатка. Это не имеет значения. gyazo.com/150dd6bd270513982357022d7dc73570
о, ошибка на вашем скриншоте отличается от того, что вы сказали. он не говорит, что Object1 равен нулю, он говорит, что data равен нулю. @devserkan ответ правильный
Я просто делаю слепое предположение, так как ваш код выше кажется прекрасным. Но как только вы укажете что-то вроде this.state.data.Object1.name в своей функции рендеринга, вы сначала получите нулевую ошибку, потому что сокет еще не вернул никаких данных. В этом случае вы можете выполнить нулевую проверку в начале вашей функции рендеринга и убедиться, что у вас действительно есть данные.

Я не так много знаю о сокетах, но поскольку вы устанавливаете состояние после первого рендеринга, данных нет, пока componentDidMount не завершит свою работу. Итак, вам нужен условный рендеринг.
const data = {
"Object1": {
"name": "1",
"rank": "2"
},
"Object2": {
"name": "3",
"rank": "4"
}
};
const fakeRequest = () => new Promise( resolve =>
setTimeout( () => resolve(data), 2000 )
);
class App extends React.Component {
state = {
data: null,
};
componentDidMount() {
fakeRequest().then( data => this.setState({data}));
}
render() {
return <div>
{!this.state.data ? "No data yet, wait 2 seconds." : this.state.data.Object1.name }
</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.data}, поскольку дочерний элемент React не может быть объектом. Вам нужно использовать значения этого объекта.
Я понимаю, в чем проблема, но я использую сокет, это сработало бы, если бы я использовал API. Постараюсь возиться и посмотреть, что я могу сделать
Итак, socket.on () - это обратный вызов, и я устанавливаю состояние через обратный вызов оттуда. Как я могу позволить setState завершиться перед рендерингом? Я не могу понять.
В чем разница использования сокета или получения данных из API здесь? В какой-то момент вы правильно понимаете данные? И, полагаю, он идет, как ручей. Итак, условный рендеринг должен работать. Вы не можете позволить setState завершить работу до первого рендеринга или приостановить рендеринг каким-либо образом. Ваш компонент монтируется и попадает в первый рендер перед componentDidMount. Вот почему мы используем здесь условный рендеринг.
Совершенно верно. Придется попробовать, когда вернусь домой. Я считаю, что ваш ответ правильный. Логически это имеет смысл, просто моя реализация неверна, и теперь я это понимаю.
Поместите
console.info(this.state)передreturnв методеrender. Что вы видите во втором рендере? Кроме того, вы не можете напрямую отображать объекты в DOM. Это не работает:{this.state.data}.