React/Webpack/Django - Uncaught TypeError: Cannot read property 'XXX' of undefined
React/Webpack/Django - Uncaught TypeError: Cannot read property 'XXX' of undefined
我正在尝试创建一个名为 'Proposals' 的 React 组件,它将呈现从 Django 后端接收到的信息的表格列表。
我正在使用 Reactable-Search component 来构成 table,但是当我尝试映射 this.props.proposals 值(例如 id 和 proj_name 到 table 单元格 - Uncaught TypeError: Cannot read 属性 'cells' of undefined
真的不确定为什么,因为当我直接在典型 html table 标签的渲染 return 中映射 this.props.proposals 时,它正在工作,即渲染后端数据正常.在其他情况下,我还在映射中使用了 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
});
});
};
};
问题是您正在异步请求提案,但 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;
}
}
当 isLoading 处于活动状态时,组件应呈现 activity 指示器或加载状态或 SearchTable
以外的任何内容:
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,
});
});
};
};
我正在尝试创建一个名为 'Proposals' 的 React 组件,它将呈现从 Django 后端接收到的信息的表格列表。
我正在使用 Reactable-Search component 来构成 table,但是当我尝试映射 this.props.proposals 值(例如 id 和 proj_name 到 table 单元格 - Uncaught TypeError: Cannot read 属性 'cells' of undefined
真的不确定为什么,因为当我直接在典型 html table 标签的渲染 return 中映射 this.props.proposals 时,它正在工作,即渲染后端数据正常.在其他情况下,我还在映射中使用了 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
});
});
};
};
问题是您正在异步请求提案,但 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;
}
}
当 isLoading 处于活动状态时,组件应呈现 activity 指示器或加载状态或 SearchTable
以外的任何内容:
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,
});
});
};
};