#javascript #reactjs #react-redux #redux-thunk
#javascript #reactjs #react-redux #redux-thunk
Вопрос:
Я извлекаю данные из службы REST. Данные возвращаются в виде массива. Это функция, которую я использую для извлечения данных.
export function fetchMessage() {
return function(dispatch) {
axios.get(`${ROOT_URL}/currencies`, {
headers: { token: localStorage.getItem('token') }
})
.then(response => {
console.log(response.data);
dispatch({
type: FETCH_MESSAGE,
payload: response.data
});
});
}
}
Результатом fetchMessage
является массив объектов.
[Object, Object, Object, Object, Object, Object]
0:Object
addedDate:"2013-08-22"
ccyCode:"CHF"
country:"SCHWIZER FRANC"
lastChangeDate:"2016-05-02"
offerRate:7.02
prevRate:8.501
prevRateDate:"2016-04-01"
rate:8.425
rateDate:"2016-05-01"
unit:1
__proto__:Object
1:Object
2:Object
3:Object
4:Object
5:Object
fetchMessage
Функция вызывается компонентом, указанным ниже.
class Feature extends Component {
componentWillMount() {
this.props.fetchMessage();
//console.log(this.props);
}
render() {
return (
<div>{this.props.message}</div>
);
}
}
function mapStateToProps(state) {
return { message: state.auth.message };
}
export default connect(mapStateToProps, actions)(Feature);
Компонент не может отобразить сообщение, потому что это
bundle.js:1256 Uncaught (in promise) Error: Objects are not valid as a React child (found: object with keys {ccyCode, country, unit, rateDate, rate, prevRateDate, prevRate, offerRate, addedDate, lastChangeDate}). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of `Feature`.(…)
Я пытался запустить карту this.props.message
, подобную этой
<div>
{this.props.message.map(
function(object){
return ('Something'
);
}
)}
</div>
Но я получаю сообщение об ошибке, в котором говорится, что я не могу работать map
дальше message
. Как я могу отобразить данные в объекте? Нужно ли мне сохранять его каким-либо другим способом? Как мне перебирать объекты для их рендеринга?
Комментарии:
1. Попробуйте что-то вроде этого:
<div>{this.props.message.ccyCode} {this.props.message.rate}</div>
и переходите оттуда.2. @ChrisG Я пробовал оба
<div>{this.props.message.ccyCod}</div>
,<div>{this.props.message.rate}</div>
и оба выдают сообщение об ошибкеUncaught TypeError: Cannot read property 'rate' of undefined
с неопределенным свойством, которое, конечно, изменитсяccyCode
, когда я попытаюсьccyCode
.
Ответ №1:
Обновление: я думаю, что ваша проблема заключается только в том, что this.props.message
она не определена при первоначальном рендеринге. Попробуйте рендеринг null
, если он не установлен.
render() {
if (!this.props.message) return null
return (
<div>
{this.props.message.map(message => {
return (
<div key={message.ccyCode}>...
{message.ccyCode} {message.rate} ...
</div>
)
})}
</div>
)
}
Мой ответ ниже все еще может быть полезен, если кто-то заинтересован в динамическом рендеринге объекта.
Я предполагаю, что вы хотите динамически отображать данные из объектов, в отличие от необходимости явно отображать каждое поле.
Попробуйте выполнить итерацию Object.keys
и отобразить данные.
<div>
{Object.keys(this.props.message).map(key => {
return (
<div key={key}> // you need a dynamic, unique key here to not get a React warning
{key}: {this.props.message[key]}
</div>
)
}
)}
</div>
Если вы хотите просто показать данные для целей отладки / проверки, я обнаружил, что это очень полезно.
<pre>
{JSON.stringify(this.props.message,null,2)}
</pre>
Комментарии:
1. Спасибо за предложения, Брэд. Строка JSON отображает весь объект. Но когда я пробую
Object.keys
настройку<div key={ccyCode}>
, то получаюReferenceError: ccyCode
, что она не определена. Я не понимаю, что вы подразумеваете под «неопределенным при первоначальном рендеринге»? Есть ли второй рендеринг? Использование оператора if, я думаю, просто приведет к отображению nothing / null?2. Во-первых, где это
ccyCode
определено? Обычно вы используете значение из сопоставленной записи. Так что вам, возможно, просто нужно сослаться на негоthis.props.message[key].ccyCode
следующим образом. Во-вторых, поскольку вы вызываете асинхронный APIcomponentWillMount()
, он будет отображаться сначала без данных, а затем во второй раз, когда ответ обновит состояние.3. Кроме того, мой ответ предполагал, что вы хотите отобразить объект в соответствии с вашим вопросом. Если вы хотите отобразить все результаты массива, я думаю, ошибка должна исчезнуть, когда вы исправите эту первоначальную ошибку рендеринга.
4. Спасибо, Брэд. Я изменил на `<div key={this.props.message[key].ccyCode}> {key}: {this.props.message[key].ccyCode} </div>`, который выдает
0: CHF 1: DKK 2: EUR...
именно то, что я хочу. Всего один вопрос, с которым я задаю свой ключ,key={this.props.message[key].ccyCode}
но затем, когда я использую `{key}`, выводится число. Чего мне не хватает в моем понимании?5. Сложно сказать .. вы хотите динамически перебирать все поля объекта или все объекты в массиве? Используете ли вы
Object.keys
по-прежнему только карту?