问题
I have one component as below. I am calling on api on its componentDidMount() event. I am not getting why am I not getting its prop value first time when component renders. Also I am not sure why component is rendering 2 times. I have below code.
import React, { Component } from "react";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import AgmtTable from "./AgmtTable";
import * as AgmtAction from "../redux/actions/AgmtAction";
class AgmtContainer extends Component {
constructor(props) {
super(props);
this.state = {};
}
fetch Agmt details.
componentDidMount() {
this.props.dispatch(
AgmtAction.getAgmtsForCustomer(
this.props.match.params.custID,
this.props.match.params.source,
this.props.token
)
);
console.log("componentDidMount", this.props.Agmts);
}
getHeaader = () => {
var tableHeadings = [
"Agmt ID",
"Start Date",
"End Date",
];
return tableHeadings.map((key) => {
return <th key={key}> {key.toUpperCase()}</th>;
});
};
getRowsData = () => {
console.log("in row data", this.props.Agmts);//here I cant see a data though its present in mapStateToProps() function. I am getting error as this.props.agreements.map is not a function.
if (this.props.Agmts) {
return this.props.Agmts.map((value) => {
const {
Agmt_ID,
Agmt_START_DATE,
End_DATE,
} = value;
return (
<tr key={Agmt_ID} className="clickable-row active">
<td> {Agmt_ID} </td>
<td> {Agmt_START_DATE} </td>
<td> {End_DATE} </td>
</tr>
);
});
}
};
render() {
return (
<React.Fragment>
<div>
<table
id="display-table"
className="table table-bordered table-hover table-responsive table-condensed table-striped table-sm"
>
<tbody>
<tr>{this.getHeaader()}</tr>
{this.getRowsData()}
</tbody>
</table>
</div>
</React.Fragment>
);
}
}
function mapStateToProps(state) {
return {
Agmts: state.AgmtsDetails.AgmtsData,//here I have a data
token: state.login.userDetails.token,
};
}
export default connect(mapStateToProps)(AgmtContainer);
Also how can I use the mapStateToProps values to set in state object. When I am running above code I am getting error as this.props.agmts.map is not a function
回答1:
The dispatch is asynchronous, so you either need to watch for result to be updated in your Redux store with componentDidUpdate
or directly return the result from the reducer.
When you get the result, you can manipulate it and store it in local state to reference in your render. Note that unless you need to reference the result in another component somewhere, then you don't need to store it in Redux, you can handle it all in within the component.
Subscribing to the store with componentDidUpdate
:
componentDidMount() {
this.props.dispatch(
AgmtAction.getAgmtsForCustomer(
this.props.match.params.custID,
this.props.match.params.source,
this.props.token
)
);
}
componentDidUpdate(prevProps) {
if (JSON.stringify(prevProps.Agmts) !== JSON.stringify(this.props.Agmts)) {
// this is the result of the dispatch
console.log(this.props.Agmts);
}
}
Returning the result directly back:
// in your AgmtAction.getAgmtsForCustomer action
export const getAgmtsForCustomer = () => (dispatch, getState) => {
return axios
.get(..........
.then((res) => {
dispatch(..........
return res.data;
})
.catch((err) => {
...
});
};
// in your `AgmtContainer` component
...
componentDidMount() {
this.props.dispatch(
AgmtAction.getAgmtsForCustomer(
this.props.match.params.custID,
this.props.match.params.source,
this.props.token
)
).then((res) => {
// this is the result of the dispatch
console.log(res);
});
}
回答2:
In getRowsData function where you are getting error "map is not a function" is due to the data you are getting in this.props.Agmts must be an object type. (Object encloses in curly brackets {}).
You can apply map function only on array not on an object. (Array encloses in square brackets [])
来源:https://stackoverflow.com/questions/61348542/how-can-i-set-the-reducers-return-value-to-state-object-in-component-in-react-j