我有一个看起来像这样的react组件。我调用cleanUpInvoices方法来格式化我的数组对象(Invoices)中的日期。这工作得很好,没有任何问题。我尝试通过setState连接到dateCleanUpResult。我得到的只是"dateCleanUpResult is not defined“。我试了这么多东西,但都不管用。我无法设置状态。
这段代码有什么问题?
下面是完整的代码
class Tester extends PureComponent {
constructor(){
super();
this.state = {
invoices:[],
startDate:'',
endDate:'',
queryResult:[],
dateCleanUpResult:[]
};
this.searchForInvoicesByDates = this.searchForInvoicesByDates.bind(this);
this.handleChange = this.handleChange.bind(this);
this.cleanUpInvoices = this.cleanUpInvoices.bind(this);
}
handleChange({ target }) {
this.setState({
[target.name]: target.value
});
}
componentDidMount() {
const getCustomerId = this.props.customer.customerId;
AXIOS_AUTHED.get(`${API}/customers/${getCustomerId}/invoices?sort=settledDate,desc`)
.then(res => {
const invoices= res.data.content;
this.setState({ invoices });
})
}
cleanUpInvoices(){
const invoice = this.state.invoices;
invoice.forEach(function(invoicer) {
const newDate = invoicer.settledDate.substring(0, invoicer.settledDate.indexOf('T'));
invoicer.settledDate = moment(newDate, 'YYYY-MM-DD').format('MM-DD-YYYY');
});
return this.setState({
dateCleanUpResult: invoice
}, () => this.state.dateCleanUpResult);
}
searchForInvoicesByDates(startDate, endDate){
var myResult = this.cleanUpInvoices();
console.log(myResult);
//now perform your date search based on the result from above
let cleanedStartDate = moment(startDate).format('MM-DD-YYYY');
let cleanedEndDate = moment(endDate).format('MM-DD-YYYY');
let filteredResult = [];
for(let i = 0; i < this.state.dateCleanUpResult.length; i++){
if(this.state.dateCleanUpResult[i].settledDate >= cleanedStartDate && this.state.dateCleanUpResult[i].settledDate <= cleanedEndDate) {
filteredResult.push(this.state.dateCleanUpResult[i]);
}
}
console.log(filteredResult);
const listItems = filteredResult.map((number) =>
<li key={number.orderNumber}>{number.orderNumber} - {moment(number.settledDate).format('MMM-DD-YYYY')} </li>
);
this.setState({queryResult:listItems});
return (
<ul>{listItems}</ul>
);
}
render() {
return (
<PageBase
navigation={['Customer Solution', 'Tester App']}
>
<div className="row">
<div className="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<Paper>
<Typography className="customer-solution-subheader" component="h3" variant="subheading">
Tester App
</Typography>
<form>
<div className="customer-form-details">
<span>DATE RANGE COVERED*</span><br/>
<span className="ctrCalendar">
<label htmlFor="start">Start date:</label>
<input type="date" id="start" name="startDate" value={this.state.startDate} onChange={this.handleChange} required></input>
</span>
<span className="ctrCalendar">
<label htmlFor="start">End date:</label>
<input type="date" id="end" name="endDate" value={this.state.endDate} onChange={this.handleChange} required></input>
</span>
<span>
<Button variant="contained" className="next-button" id="btnSearchDates" onClick={() =>this.searchForInvoicesByDates(this.state.startDate, this.state.endDate)}>Search</Button><br/><br/>
</span>
<p>Search Result (Invoices/Dates)</p>
<div role="content" className="invContentParent">
<div name="teach" id="invContentChild">
</div>
</div>
</div>
</form>
</Paper>
</div>
</div>
</PageBase>
);
}
}
export default Tester;发布于 2019-07-13 04:09:41
这几乎是正确的,但令人欣慰的是,当您返回数组的时,它可能只是您在组件的state处初始化的空数组。
我们修复了将一个回调函数传递给setState方法,这个函数返回你想要的状态,更新后的状态,对吗?
该回调函数将在确保设置了新的state之后调用,并且,我们还返回setState函数,因为它是返回新状态的函数。
return this.setState({
dateCleanUpResult: invoice
}, () => this.state.dateCleanUpResult);对于这个问题,ARTICLE是一个很好的解释。
发布于 2019-07-13 04:25:16
我创建了一个jsfiddle,显示您可以更新案例中的状态。http://jsfiddle.net/efp82rjg/3/
我认为你得到了一个问题,因为你假设cleanUpInvoices()将返回状态的更新值。但它不会,因为setState是异步的,即使值将被更新,但它不会向您显示更新后的值。如果您想在setState()之后访问更新后的值,那么可以使用在setState函数之后可用的回调。请阅读此处的文档:https://reactjs.org/docs/react-component.html#setstate
class Hello extends React.Component {
constructor() {
super();
this.state = {
invoices: [
{ settledDate: 'no' },
{ settledDate: 'no' },
],
dateCleanUpResult: [],
};
this.cleanUpInvoices = this.cleanUpInvoices.bind(this);
}
cleanUpInvoices() {
const invoice = this.state.invoices;
invoice.forEach((invoicer) => {
invoicer.settledDate = 'testing';
});
this.setState({
dateCleanUpResult: invoice,
});
return this.state.dateCleanUpResult;
}
render() {
return (
<div>
<button onClick={this.cleanUpInvoices}>test</button>
{this.state.dateCleanUpResult.map(item => (
<div>{item.settledDate}</div>
))}
</div>
);
}发布于 2019-07-13 05:16:56
我假设您在searchForInvoicesByDateMethod中记录返回值cleanUpInvoices时收到的值为"undefined“。虽然这是setState异步特性的结果,但是实现setState回调不会解决这个问题(如果没有更多的回调,它只会让您访问该处理程序范围内的更新状态)。如果你想坚持你当前的实现,我会返回一个promise,并异步/等待返回的promise值。当调用cleanUpInvoices时,这将延迟searchForInvoicesByDates方法中代码的执行。
cleanUpInvoices(){
// Avoid directly mutating state and generating circular reference by creating new array with map
const invoice = this.state.invoices.map(invoice => Object.assign({}, invoice));
//.....
//.....
return new Promise((res) => {
return this.setState({
dateCleanUpResult: invoice
}, () => res(this.state.dateCleanUpResult)));
}
}
////////
async searchForInvoicesByDates(startDate, endDate){
var myResult = await this.cleanUpInvoices();
//....
}为了不偏离所提出的问题,这里有另一个可能简化实现的快速想法。看起来您最初是在componentDidMount上进行API调用以检索全部发票,然后根据用户输入按日期生成一个子集。是否有必要将生成的子集保持在状态?每次按日期搜索发票时,您似乎希望使用从API返回的全部内容作为筛选器的起点。如果是这种情况,您可以立即从cleanUpInvoices返回结果--不需要状态更新。当然,如果您需要发票子集用于进一步的引用或操作,则情况会有所不同。
https://stackoverflow.com/questions/57013235
复制相似问题