从表单构建器中深层嵌套的子项自下而上地更新状态
React Updating state bottom up from deeply nested children in a form builder
我需要帮助思考从深度嵌套 children/grandchildren 更新父状态的最佳方法。
我正在使用 React 创建一个表单生成器,它允许用户通过在 localeStorage 中保存持久状态来创建、预览和导出表单。一个表格有问题,每个问题都有一个可能的子问题。
我的想法是在app层保持所有问题的状态,赋值localStorage.setItem('questions',this.state.questions)
数据结构如下:
[
{ question='question 1',
type='text',
condition=null,
isSub= false,
subQ=[{
question='sub question 1',
...
isSub=true,
subQ=[]
}]
},
{
question='question 1',
...
isSub= false,
subQ=[]
},
question='question 1',
...
isSub= false,
subQ=[]
}
]
我的Component层级结构是App -> QuestionForm -> Question。
App 保持所有问题的状态,Question 管理自己的 onChange 调用 updateInputValue 更新值,然后调用绑定到 QuestionForm 组件的 updateParent(key, update)。 QuestionForm 然后调用绑定到 App 的 updateQuestions(update)。这适用于最外层的问题。使用对子问题所做的更改来更新 App 状态的最佳方法是什么?
class Question extends Component{
constructor(props){
super(props)
this.state = {
question: props.question
}
this.updateInputValue = this.updateInputValue.bind(this)
}
.....
updateInputValue(e){
let { name, value } = e.target,
question = {...this.props.question }
if( !name ){
value = e.target.parentElement.getAttribute('name') ||
e.target.getAttribute('name')
name = 'type'
}
question[name] = value
this.setState({question: question})
this.props.updateParent(this.props.id, question)
}
这就是我在问题中呈现每个问题的子问题的方式
渲染()组件
{ question.subQ.map( (q, i) =>
<Question key={i}
question={q}
updateParent={this.props.updateParent} /> ) }
QuestionForm组件内部的updateParent函数
updateParent = (key, prop) => {
let questions = {...this.state.questions }
questions[key] = prop
this.props.updateQuestions(questions)
}
最后,App组件
class App extends Component {
constructor(props){
super(props)
this.state = {
questions: sample,
activeItem: 'Create'
}
this.checkStorage = checkStorage
this.addQuestion = addQuestion.bind(this)
this.handleTabClick = this.handleTabClick.bind(this)
this.updateQuestions = this.updateQuestions.bind(this)
}
updateQuestions(update){
this.setState({questions: update})
}
我正在考虑一种自下而上的方法,通过跟踪 parentKeys 并爬上树直到 'isSub' === false。有没有更好的方法来解决这个问题?
如果 App 要存储您的问题状态,我认为最简单的方法就是为 App 提供一个 updateQuestion 方法,如下所示:
updateQuestion(path, value) {
const { questions } = this.state;
_.set(questions, path, value);
this.setState({ questions });
}
在这里,我们使用 lodash's set
method 来遍历数据结构并更改您需要的任何值。现在,我们可以绑定这个函数并将其作为 prop 传递给每个问题,并根据需要传递给每个子问题。
然后,在您的渲染方法中,当您将每个问题映射到您的数据数组时,动态地为其分配一个 path
道具,该道具反映您将在您的状态中更改的值的位置该特定问题调用 updateQuestion。
将应用程序的 state.questions(或其一部分)作为道具传递给每个问题,您可以避免让它们保持自己的状态,这意味着除非您需要生命周期挂钩,否则您可以将问题变成一个功能组件。
不过,老实说,当您发现自己不得不像这样冒泡状态时,是时候问问自己 redux 是否不合适了。如果您以前没有使用过它,您将有一些初始增长的主电源,但它会为您节省很多精力和不必要的复杂性。
我需要帮助思考从深度嵌套 children/grandchildren 更新父状态的最佳方法。
我正在使用 React 创建一个表单生成器,它允许用户通过在 localeStorage 中保存持久状态来创建、预览和导出表单。一个表格有问题,每个问题都有一个可能的子问题。
我的想法是在app层保持所有问题的状态,赋值localStorage.setItem('questions',this.state.questions)
数据结构如下:
[
{ question='question 1',
type='text',
condition=null,
isSub= false,
subQ=[{
question='sub question 1',
...
isSub=true,
subQ=[]
}]
},
{
question='question 1',
...
isSub= false,
subQ=[]
},
question='question 1',
...
isSub= false,
subQ=[]
}
]
我的Component层级结构是App -> QuestionForm -> Question。 App 保持所有问题的状态,Question 管理自己的 onChange 调用 updateInputValue 更新值,然后调用绑定到 QuestionForm 组件的 updateParent(key, update)。 QuestionForm 然后调用绑定到 App 的 updateQuestions(update)。这适用于最外层的问题。使用对子问题所做的更改来更新 App 状态的最佳方法是什么?
class Question extends Component{
constructor(props){
super(props)
this.state = {
question: props.question
}
this.updateInputValue = this.updateInputValue.bind(this)
}
.....
updateInputValue(e){
let { name, value } = e.target,
question = {...this.props.question }
if( !name ){
value = e.target.parentElement.getAttribute('name') ||
e.target.getAttribute('name')
name = 'type'
}
question[name] = value
this.setState({question: question})
this.props.updateParent(this.props.id, question)
}
这就是我在问题中呈现每个问题的子问题的方式 渲染()组件
{ question.subQ.map( (q, i) =>
<Question key={i}
question={q}
updateParent={this.props.updateParent} /> ) }
QuestionForm组件内部的updateParent函数
updateParent = (key, prop) => {
let questions = {...this.state.questions }
questions[key] = prop
this.props.updateQuestions(questions)
}
最后,App组件
class App extends Component {
constructor(props){
super(props)
this.state = {
questions: sample,
activeItem: 'Create'
}
this.checkStorage = checkStorage
this.addQuestion = addQuestion.bind(this)
this.handleTabClick = this.handleTabClick.bind(this)
this.updateQuestions = this.updateQuestions.bind(this)
}
updateQuestions(update){
this.setState({questions: update})
}
我正在考虑一种自下而上的方法,通过跟踪 parentKeys 并爬上树直到 'isSub' === false。有没有更好的方法来解决这个问题?
如果 App 要存储您的问题状态,我认为最简单的方法就是为 App 提供一个 updateQuestion 方法,如下所示:
updateQuestion(path, value) {
const { questions } = this.state;
_.set(questions, path, value);
this.setState({ questions });
}
在这里,我们使用 lodash's set
method 来遍历数据结构并更改您需要的任何值。现在,我们可以绑定这个函数并将其作为 prop 传递给每个问题,并根据需要传递给每个子问题。
然后,在您的渲染方法中,当您将每个问题映射到您的数据数组时,动态地为其分配一个 path
道具,该道具反映您将在您的状态中更改的值的位置该特定问题调用 updateQuestion。
将应用程序的 state.questions(或其一部分)作为道具传递给每个问题,您可以避免让它们保持自己的状态,这意味着除非您需要生命周期挂钩,否则您可以将问题变成一个功能组件。
不过,老实说,当您发现自己不得不像这样冒泡状态时,是时候问问自己 redux 是否不合适了。如果您以前没有使用过它,您将有一些初始增长的主电源,但它会为您节省很多精力和不必要的复杂性。