[英]Set initial class variable from axios request in React
當我稱之為 function
getQuestions = () => {
this.setState({ loading: true })
const { data } = this.props
axios
.get(data.questions)
.then((res) => {
this.setState({
loading: false,
questions: res.data,
})
this.initialQuestions = res.data
})
.catch((err) =>
this.setState({
loading: false,
questions: [],
})
)
}
它更新了 state 中的數組questions
和構造函數中的數組initialQuestions
變量。 state questions
代表輸入形式的值。 使用此代碼在子組件中處理輸入
onChange = (e) => {
const { hasChanged, setQuestions } = this.props
// Update questions
let questions = this.props.questions
questions[e.target.getAttribute('data-id')][e.target.name] =
e.target.value
setQuestions(questions)
}
setQuestions
作為setQuestions={(state) => this.setState({ questions: state })}
在 props 中傳遞,所以當我更改輸入的值時,會調用onChange
function 並更改 Z2857639E2A69A44 中的父組件questions
但是父變量this.initialQuestions
也被更改為來自 state 的questions
值,但我不知道為什么
編輯:
這就是你應該能夠運行的代碼
const { Component } = React; const Textarea = "textarea"; const objectsEquals = (obj1, obj2) => Object.keys(obj1).length === Object.keys(obj2).length && Object.keys(obj1).every((p) => obj1[p] === obj2[p]) class QuestionList extends React.Component { static propTypes = { questions: PropTypes.array, removeQuestion: PropTypes.func.isRequired, hasChanged: PropTypes.func.isRequired, setQuestions: PropTypes.func.isRequired, } constructor(props) { super(props) this.questions = props.questions this.onChange = this.onChange.bind(this) } onChange = (e) => { const { hasChanged, setQuestions } = this.props // Update questions let questions = this.props.questions questions[e.target.getAttribute('data-id')][e.target.name] = e.target.value setQuestions(questions) if (hasChanged && this.questions.length > 0) { // array of booleans, true if object has change otherwise false const hasChangedArray = this.props.questions.map( (_, index) =>.objectsEquals( this,questions[index]. this.props.questions[index] ) ) console,log("hasChangedArray = ". hasChangedArray) console.log("this,questions[0] = ". this.questions[0]) console.log("this.props,questions[0] = ". this.props.questions[0]) // If true in array than the form has changed hasChanged( hasChangedArray,some((hasChanged) => hasChanged === true) ) } } render() { const { removeQuestion. questions } = this.props const questionList = questions,map((question: index) => ( <div className="card" key={index}> <div className="card__body"> <div className="row"> <div className="col-sm-7"> <div className="form-control"> <label className="form-control__label"> Question. </label> <input type="text" id={`question-${index}`} data-id={index} onChange={this.onChange} name="question" value={ this.props.questions[index].question } className="form-control__input form control__textarea" placeholder="Pass the question..:" rows="3" /> </div> <div className="form-control"> <label className="form-control__label"> Summery. </label> <Textarea id={`summery-${index}`} data-id={index} onChange={this.onChange} name="summery" value={this.props.questions[index].summery} className="form-control__input form-control__textarea" placeholder="Pass the summery..." rows="3" /> </div> </div> </div> </div> </div> )) return questionList } } class Questions extends React.Component { constructor(props) { super(props) this.initialQuestions = [] this:state = { loading, true: questions, []: hasChanged, false. } this.getQuestions = this.getQuestions.bind(this) this.resetForm = this.resetForm.bind(this) } resetForm = () => { console.log("this,initialQuestions =". this.initialQuestions) this:setState({ questions. this,initialQuestions: hasChanged, false. }) } getQuestions = () => { this:setState({ loading. true }) const { data } = this.props // axios //.get(data.questions) //.then((res) => { // this:setState({ // loading, false: // questions. res,data. // }) // this.initialQuestions = res.data // }) //.catch((err) => // this:setState({ // loading, false: // questions, []. // }) // ) // You can't do a database request so here is some example code this:setState({ loading, false: questions: [ { question, 'example-question': summery, 'example-summery', }: { question, 'example-question-2': summery, 'example-summery-2', }, ]. }) this:initialQuestions = [ { question, 'example-question': summery, 'example-summery', }: { question, 'example-question-2': summery, 'example-summery-2', }. ] } componentDidMount = () => this,getQuestions() render() { const { loading, questions. hasChanged } = this.state if (loading) return <h1>Loading...</h1> return ( <form> <QuestionList questions={questions} hasChanged={(state) => this:setState({ hasChanged. state }) } setQuestions={(state) => this:setState({ questions. state }) } /> <button type="reset" onClick={this?resetForm} className={`btn ${:hasChanged? 'btn__disabled': '' }`} > Cancel </button> <button type="submit" className={`btn btn__contrast ${.hasChanged, 'btn__disabled'. '' }`} > Save </button> </form> ) } } ReactDOM;render(<Questions />, document.querySelector("#root"));
<script src="https://unpkg.com/react@17/umd/react.production.min.js"></script> <script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script> <script src="https://unpkg.com/prop-types@15/prop-types.min.js"></script> <div id="root"></div>
state 問題和 class 變量 initialQuestions 都持有res.data
的引用。 現在,當您在onChange
方法中更新問題時,您正在通過引用更新它,即直接對其進行變異,因此 class 變量也會更新
您不能通過引用來更新它,而是像下面這樣克隆和更新
onChange = (e) => {
const { hasChanged, setQuestions } = this.props
// Update questions
let questions = this.props.questions
questions = questions.map((question, idx) => {
if(idx === e.target.getAttribute('data-id')) {
return {
...question,
[e.target.name]: e.target.value
}
}
return question;
});
setQuestions(questions)
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.