我正在使用Meteor与React,react-Router和createContainer。当我转到链接时,我遇到了一个组件的问题:
127.0.0.1:27017/testimonial/edit/id
似乎在构造函数中,在尝试定义状态时,props仍未定义:怎么来的?无论如何,当道具被发送时,组件是否应该重新渲染?
我尝试使用componentWillReceiveProps(nextProps)钩子解决问题,但它也没有用。
它给出了以下错误(第14行是构造函数方法中的this.state函数):
Uncaught TypeError: Cannot read property 'author' of undefined
at new TestimonialEditItem (TestimonialEditItem.js:14)
at modules.js?hash=74f0dc7…:20359
at measureLifeCyclePerf (modules.js?hash=74f0dc7…:20140)
at ReactCompositeComponentWrapper._constructComponentWithoutOwner (modules.js?hash=74f0dc7…:20358)
at ReactCompositeComponentWrapper._constructComponent (modules.js?hash=74f0dc7…:20344)
at ReactCompositeComponentWrapper.mountComponent (modules.js?hash=74f0dc7…:20252)
at Object.mountComponent (modules.js?hash=74f0dc7…:13083)
at ReactCompositeComponentWrapper.performInitialMount (modules.js?hash=74f0dc7…:20435)
at ReactCompositeComponentWrapper.mountComponent (modules.js?hash=74f0dc7…:20322)
at Object.mountComponent (modules.js?hash=74f0dc7…:13083)
Exception from Tracker recompute function: Invariant Violation: Attempted to update component `TestimonialEditItem` that has already been unmounted (or failed to mount).
at invariant (http://127.0.0.1:3000/packages/modules.js?hash=74f0dc773a707103dd7edec08a76b26338e4d966:4095:15)
at ReactCompositeComponentWrapper.updateComponent (http://127.0.0.1:3000/packages/modules.js?hash=74f0dc773a707103dd7edec08a76b26338e4d966:20648:63)
at ReactCompositeComponentWrapper.receiveComponent (http://127.0.0.1:3000/packages/modules.js?hash=74f0dc773a707103dd7edec08a76b26338e4d966:20611:10)
at Object.receiveComponent (http://127.0.0.1:3000/packages/modules.js?hash=74f0dc773a707103dd7edec08a76b26338e4d966:13162:22)
at ReactCompositeComponentWrapper._updateRenderedComponent (http://127.0.0.1:3000/packages/modules.js?hash=74f0dc773a707103dd7edec08a76b26338e4d966:20818:23)
at ReactCompositeComponentWrapper._performComponentUpdate (http://127.0.0.1:3000/packages/modules.js?hash=74f0dc773a707103dd7edec08a76b26338e4d966:20788:10)
at ReactCompositeComponentWrapper.updateComponent (http://127.0.0.1:3000/packages/modules.js?hash=74f0dc773a707103dd7edec08a76b26338e4d966:20709:12)
at ReactCompositeComponentWrapper.performUpdateIfNecessary (http://127.0.0.1:3000/packages/modules.js?hash=74f0dc773a707103dd7edec08a76b26338e4d966:20625:12)
at Object.performUpdateIfNecessary (http://127.0.0.1:3000/packages/modules.js?hash=74f0dc773a707103dd7edec08a76b26338e4d966:13194:22)
at runBatchedUpdates (http://127.0.0.1:3000/packages/modules.js?hash=74f0dc773a707103dd7edec08a76b26338e4d966:12769:21)
文件的重要部分如下:
AppRouter:
const AppRouter = () => (
<BrowserRouter>
<div>
<Header />
<Switch>
<Route path="/" component={Index} exact={true} />
<Route path="/admin" render={() => (
isAdmin() ? (
<Admin />
) : (
<Redirect to="/login"/>
)
)}/>
<Route path="/testimonial/edit/:id" component={TestimonialEditItem} />
<Route path="/reference/edit/:id" component={ReferenceEditItem} />
<Route path="/team" component={Team} />
<Route path="/references" component={References} />
</Switch>
<Footer />
</div>
</BrowserRouter>
);
TestimonialEditItem.js:
import React from 'react';
import PropTypes from 'prop-types';
import { Meteor } from 'meteor/meteor';
import moment from 'moment';
import { createContainer } from 'meteor/react-meteor-data';
import { Testimonials } from './../../api/testimonials';
export class TestimonialEditItem extends React.Component {
constructor(props){
super(props);
this.state = {
author: props.testimonial.author,
body: props.testimonial.body,
company: props.testimonial.company,
position: props.testimonial.position
}
}
componentWillReceiveProps(nextProps){
this.setState(() => ({
author: nextProps.testimonial.author,
body: nextProps.testimonial.body,
company: nextProps.testimonial.company,
position: nextProps.testimonial.position
}))
}
handleBodyChange(e) {
const body = e.target.value;
this.setState(() => ({ body }));
}
handleAuthorChange(e) {
const author = e.target.value;
this.setState(() => ({ author }));
}
handleCompanyChange(e) {
const company = e.target.value;
this.setState(() => ({ company }));
}
handlePositionChange(e) {
const position = e.target.value;
this.setState(() => ({ position }));
}
onSubmit(e) {
e.preventDefault();
console.log(this.state.body);
this.props.call('testimonials.update', this.props.testimonial._id, this.state.body, this.state.author, this.state.company, this.state.position);
this.props.history.push('/admin');
}
renderEditForm() {
console.log(this.props.ready);
return(
<div className="container editTestimonial__form">
Author: <input onChange={this.handleAuthorChange.bind(this)} value={this.state.author} placeholder="Author" type="text"/>
Company: <input onChange={this.handleCompanyChange.bind(this)} value={this.state.company} placeholder="Company" type="text"/>
Position: <input onChange={this.handlePositionChange.bind(this)} value={this.state.position} placeholder="Position" type="text"/>
Body: <textarea onChange={this.handleBodyChange.bind(this)} value={this.state.body} placeholder="Body"></textarea>
<button className="editTestimonial__button" onClick={this.onSubmit.bind(this)}>Edit Testimonial</button>
</div>
)
}
render() {
return (
<div className="editTestimonial">
{ this.props.ready ? this.renderEditForm() : 'Pas de testimonial' }
</div>
);
}
}
export default createContainer((props) => {
const sub = Meteor.subscribe('testimonials');
console.log(props.match.params.id);
return {
ready: sub.ready(),
testimonial: Testimonials.findOne(props.match.params.id),
call: Meteor.call
}
}, TestimonialEditItem)
非常感谢任何帮助/想法。
答案 0 :(得分:2)
您的问题是,props.testimonial
将是undefined
,直到订阅完成。由于props.testimonial
为undefined
,因此在尝试获取props.testimonial.author
时无法读取错误。您可以做的是使用默认值设置初始状态。
实施例
constructor(props){
super(props);
this.state = {
author: props.testimonial ? props.testimonial.author : '',
body: props.testimonial ? props.testimonial.body : '',
company: props.testimonial ? props.testimonial.company : '',
position: props.testimonial ? props.testimonial.position : ''
}
}