我在子组件中有一个用于调试目的的按钮,用于在其父组件中打印当前状态。当它打印时,这就是我想要的状态。当我点击同一子组件中的另一个按钮时,通过删除一些属性,状态在父级中发生变化。
请注意现在缺少Id
和SEO_CSEO_Survey_Questions__r
属性。
子组件
import React, { Component } from 'react';
import { Link } from 'react-router';
class Index extends Component {
constructor(props){
super(props)
this.state = {
selected: 'created'
}
this.updatePreview = this.updatePreview.bind(this);
this.renderEditArea = this.renderEditArea.bind(this);
}
isActive(value) {
return 'slds-tabs--default__item '+((value===this.state.selected) ?'slds-active':'');
}
updatePreview(e){
const updatedPreview = {
...this.props.selectedPreview,
[e.target.name]: e.target.value
};
this.props.update(updatedPreview)
}
// determines which type of edit area should display
// survey settings or question
renderEditArea() {
let selected = this.props.selectedPreview;
let hasNameKey = "Name" in selected;
if(hasNameKey){
return (
<div>
<input
onChange={(e) => this.updatePreview(e)}
name="Name"
type="text"
className="slds-input"
value={selected.Name ? selected.Name : ''}
/>
<input
onChange={(e) => this.updatePreview(e)}
name="SEO__Welcome_Text__c"
type="text"
className="slds-input"
value={selected.SEO__Welcome_Text__c ? selected.SEO__Welcome_Text__c : ''}
/>
</div>
)
}else {
return (
<input
onChange={(e) => this.updatePreview(e)}
name="SEO__Question__c"
type="text"
className="slds-input"
value={selected.SEO__Question__c ? selected.SEO__Question__c : ''}
/>
)
}
}
render() {
return (
<div className="slds-size--1-of-1 slds-medium-size--4-of-5 slds-large-size--4-of-5">
<div className="slds-tabs--default">
<h2 className="slds-text-heading--small slds-p-top--x-small" style={{position: "absolute"}}>
<button onClick={this.props.addQuestion} className="slds-button slds-button--icon slds-p-left--xx-small" title="add sur">
<svg className="slds-button__icon slds-button__icon--medium" aria-hidden="true">
<use xlinkHref={addIcon}></use>
</svg>
<span className="slds-assistive-text">Add Question</span>
</button>
</h2>
<ul className="slds-tabs--default__nav" style={{justifyContent: "flex-end"}}>
<Link to="/"className="slds-button slds-button--neutral">Back</Link>
<button onClick={this.props.save} className="slds-button slds-button--brand">Save</button>
<button onClick={this.props.currentState} className="slds-button slds-button--brand">Current State</button>
</ul>
</div>
<div className="slds-grid slds-wrap slds-grid--pull-padded">
{this.renderEditArea()}
</div>
</div>
);
}
}
export default Index;
父
import React, { Component } from 'react';
import { getQuestions, addQuestion, deleteQuestion, newSurveyQuestions, updateSurveyQuestions, EMPTY_SURVEY } from './helpers';
import SideBar from './survey/SideBar';
import MainArea from './survey/Index';
class Survey extends Component {
constructor(props) {
super(props)
this.state = {
survey: [],
selectedPreview: []
}
this.componentWillMount = this.componentWillMount.bind(this);
this.save = this.save.bind(this);
this.setSelectedPreview = this.setSelectedPreview.bind(this);
this.currentState = this.currentState.bind(this);
}
// if the url is `/survey/new`, create an empty survey
// to save for later.
// else if there is an id in the url, load the survey and questions
componentWillMount(){
if(this.props.pathname === "/survey/new") {
this.setState({
survey: EMPTY_SURVEY,
selectedPreview: EMPTY_SURVEY[0]
})
} else if (this.props.params.surveyId){
getQuestions(this.props.params.surveyId).then(survey => {
// 'survey' contains all the questions
this.setState({
survey,
selectedPreview: survey[0]
});
});
}
}
currentState() {
console.log('clicking Current State');
console.log(this.state.survey[0]);
}
// saves a new survey with associated newly created questions
// or saves an existing survey with associated questions
save() {
console.log('clicking Save');
console.log(this.state.survey[0]);
// if the url is set to survey/new
// save new survey with associated newly created questions
if(this.props.pathname === "/survey/new") {
newSurveyQuestions(this.state.survey).then( id => {
this.context.router.transitionTo(`/survey/id/${id}`);
})
// else update survey and questions
} else {
updateSurveyQuestions(this.state.survey);
}
}
// sets selectedPreview for the entire component and
// its children
setSelectedPreview(selectedPreview) {
this.setState({selectedPreview});
}
render() {
return (
<div className="slds-grid slds-wrap slds-grid--pull-padded">
<SideBar
survey={this.state.survey}
setSelectedPreview={this.setSelectedPreview}
deleteQuestion={this.deleteQuestion}
/>
<MainArea
addQuestion={this.addQuestion}
selectedPreview={this.state.selectedPreview}
update={this.update}
save={this.save}
currentState={this.currentState}
/>
</div>
);
}
}
Survey.contextTypes = {
router: React.PropTypes.object
}
export default Survey;
帮助功能
export function updateSurveyQuestions(survey) {
// create proper url for update request
const requestURL = `${URL + survey[0].attributes.url}`;
// save questions for later update requests
const questions = survey[0].SEO__CSEO_Survey_Questions__r.records;
let s = [...survey];
// remove properties for proper body format
delete s[0].Id;
delete s[0].SEO__CSEO_Survey_Questions__r;
delete s[0].attributes;
axios.patch(requestURL, s[0], API_TOKEN);
questions.forEach( question => {
// save request url for later
let requestURL = `${URL + question.attributes.url }`;
// remove properites for proper body format
delete question.attributes;
delete question.Id;
axios.patch(requestURL, question, API_TOKEN);
})
}
当我删除save()
中的所有代码({1}}除外)时,它会按预期打印。
答案 0 :(得分:1)
tl; dr:您的代码运行正常。您所看到的是对象和控制台如何工作的结果。做
console.log(this.state.survey[0].Id);
而不是看到该属性确实存在。
另见Is Chrome's JavaScript console lazy about evaluating arrays?
当我删除save()中的所有代码时,除了console.log之外,它会按预期打印。
这似乎表明该代码正在改变对象。例如。 updateSurveyQuestions
或newSurveyQuestions
可能会移除这些属性。
您必须记住,您在控制台中看到的输出是在您展开属性,不时计算的console.log
叫做。实际上,i
旁边的小Object
图标会告诉您。当你将鼠标悬停在它上面时说:
以下评估价值
以下是您遇到的简化示例:展开对象并注意它是空的,即使我们在调用 理想情况下,console.dir
后打开了(打开浏览器的控制台):< / p>
var obj = {foo: 42};
console.dir(obj);
delete obj.foo;
updateSurveyQuestions
或newSurveyQuestions
不会直接改变对象,而是克隆它,对克隆进行必要的更改,然后更新组件状态(如果需要)。例如。克隆对象的简单方法是通过Object.assign
:var copy = Object.assign({}, this.state.survey[0]);