Я пытаюсь создать компонент React под названием «Предложения», который будет отображать табличный список информации, полученной от бэкэнда Django.
Я использую Компонент Reactable-Search для формирования таблицы, но постоянно получаю сообщение об ошибке, когда пытаюсь сопоставить значения this.props.proposals, такие как id и proj_name, с ячейками таблицы — Uncaught TypeError: невозможно прочитать свойства «ячейки» неопределенного
На самом деле не уверен, почему, потому что, когда я сопоставляю this.props.proposals непосредственно в возврате рендеринга типичных тегов html-таблицы, он работает, т.е. отображает бэкэнд-данные в порядке. и я также использовал компонент Reactable-Search с сопоставлением в других случаях, и он работал нормально.
Вывод журнала this.props.proposals также показывает правильный массив объектов...:

Очень ценю, если кто-то может подтолкнуть меня в правильном направлении, спасибо!
Компонент «Предложения»:
import React, { Component } from "react";
import { connect } from "react-redux";
import SearchTable from "reactable-search";
import { proposals } from "../actions";
class Proposals extends Component {
componentDidMount() {
this.props.fetchProposals();
}
constructor(props) {
super(props);
this.state = {};
}
render() {
var rows = this.props.proposals.map(p => ({
selected: this.state.selectedRow === p.id,
onClick: () => {
this.setState({ selectedRow: p.id });
},
cells: {
"#": p.id,
"Project Name": p.proj_name
}
}));
return (
<SearchTable
showExportCSVBtn = {true}
searchPrompt = "Type to search"
rows = {rows}
/>
);
}
}
const mapStateToProps = state => {
return {
proposals: state.proposals
};
};
const mapDispatchToProps = dispatch => {
return {
fetchProposals: () => {
dispatch(proposals.fetchProposals());
}
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(Proposals);Редуктор предложений:
const initialState = [];
export default function proposals(state = initialState, action) {
switch (action.type) {
case "FETCH_PROPOSALS":
return [...action.proposals];
default:
return state;
}
}Действие предложений
export const fetchProposals = () => {
return dispatch => {
let headers = { "Content-Type": "application/json" };
return fetch("/api/proposals/", { headers })
.then(res => res.json())
.then(proposals => {
return dispatch({
type: "FETCH_PROPOSALS",
proposals
});
});
};
};Привет, Юджин. Когда я регистрирую this.props.proposals, он выводит ожидаемый массив объектов... Я также добавил файлы редуктора и действия. Благодарность



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Проблема в том, что вы запрашиваете предложения асинхронно, но компонент SearchTable, похоже, не работает с пустым начальным объектом предложений. Попробуйте передать пустой массив в качестве реквизита rows, и вы получите точно такое же сообщение об ошибке о неопределенном объекте.
Чтобы исправить это, вам нужно показывать индикатор загрузки вместо SearchTable во время загрузки предложений. Ваш редьюсер должен выглядеть примерно так, за исключением того, что вы также должны обрабатывать случай сбоя:
const initialState = { isLoading: false, error: null, proposals: [] };
export default function proposals(state = initialState, action) {
switch (action.type) {
case "FETCH_PROPOSALS":
return {
...state,
isLoading: true
};
case "FETCH_PROPOSALS_SUCCESS":
return {
...state,
isLoading: false,
proposals: action.proposals
};
case "FETCH_PROPOSALS_FAILURE":
return {
...state,
isLoading: false,
error: action.error,
};
default:
return state;
}
}
Затем компонент должен отображать индикатор активности или статус загрузки или что-то еще, кроме SearchTable, когда isLoading активен:
import React, { Component } from "react";
import { connect } from "react-redux";
import SearchTable from "reactable-search";
import { proposals } from "../actions";
class Proposals extends Component {
componentDidMount() {
this.props.fetchProposals();
}
constructor(props) {
super(props);
this.state = {};
}
render() {
const { proposals, error, isLoading } = this.props;
if (isLoading) {
return <div>Loading...</div>;
}
if (error) {
return <div>{error.message}</div>;
}
if (proposals.length === 0) {
return <div>No proposals</div>;
}
var rows = proposals.map(p => ({
selected: this.state.selectedRow === p.id,
onClick: () => {
this.setState({ selectedRow: p.id });
},
cells: {
"#": p.id,
"Project Name": p.proj_name
}
}));
return (
<SearchTable
showExportCSVBtn = {true}
searchPrompt = "Type to search"
rows = {rows}
/>
);
}
}
const mapStateToProps = state => {
return {
proposals: state.proposals.proposals,
isLoading: state.proposals.isLoading,
error: state.proposals.error,
};
};
const mapDispatchToProps = dispatch => {
return {
fetchProposals: () => {
dispatch(proposals.fetchProposals());
}
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(Proposals);
И преобразователь действие:
export const fetchProposals = () => {
return dispatch => {
dispatch({type: "FETCH_PROPOSALS"});
let headers = { "Content-Type": "application/json" };
return fetch("/api/proposals/", { headers })
.then(res => res.json())
.then(proposals => {
dispatch({
type: "FETCH_PROPOSALS_SUCCESS",
proposals
});
})
.catch(error => {
dispatch({
type: "FETCH_PROPOSALS_FAILURE",
error,
});
});
};
};
Вау - большое спасибо за четкий и быстрый ответ и объяснение. Решение правильное! Я застрял на этом весь день, ура
Можете ли вы опубликовать
initialStateвашего редуктораproposals? Попробуйте зарегистрироватьthis.props.proposalsв методеrenderи посмотреть, действительно ли он выводит ожидаемый результат.