2017-07-10 17 views
0

我需要幫助,圍繞從深層嵌套的子/孫更新父狀態的最佳方法。React從表單構建器中的深層嵌套子節點向下更新狀態

我使用React創建表單生成器,允許用戶通過在localeStorage中保存持久狀態來創建,預覽和導出表單。表格有問題,每個問題都有可能的子問題。

我的想法是保持的應用層上的所有問題的狀態,分配localStorage.setItem(「問題」,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=[] 
     } 
    ] 

我的組件層次結構是應用程序 - >問題表達式 - >問題。 應用程序保持所有問題的狀態,問題管理自己的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) 
     } 

最後,應用程序組件

  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。有沒有更好的方法來解決這個問題?

+0

那麼另一種方法是隻需要使用redux或類似的東西傳遞給每個組件的狀態標誌包。 –

回答

0

如果應用程序是要保存你的問題的狀態,在我看來,最簡單的事情是隻給應用程序的updateQuestion方法是這樣的:

updateQuestion(path, value) { 
    const { questions } = this.state; 
    _.set(questions, path, value); 
    this.setState({ questions }); 
} 

在這裏,我們使用lodash's set method以橫截數據結構並改變你需要的任何值。現在,我們可以綁定這個函數,並將其作爲每個問題的支持,並根據需要傳遞給每個子問題。

然後,在渲染方法中,當您將每個問題映射到數據數組時,動態分配一個path道具,該道具反映了在特定問題調用updateQuestion時將改變的值的位置。

將應用程序的state.questions(或其一部分)作爲prop傳遞給每個Question,並且可以避免讓它們保持自己的狀態,除非需要生命週期鉤子,否則可以將Question轉換爲功能零件。然而,當你發現自己不得不像這樣冒泡時,老實說,現在是時候問自己,是不是要走了。如果您之前沒有使用它,您將擁有一些初始增長的主幹線,但它會爲您節省大量的工作和不必要的複雜性。

+0

感謝您的回覆。我以前沒有用過redux,時間是個問題。 – nzoLogic

+0

因爲我必須在localStorage中以持久狀態存儲數據,所以我想知道是否有辦法採取Reacts單向數據流原則,並讓每個Question組件的實例與它對localStorage的引用並行運行並動態更新persistentData基於問題組件的當前狀態。 – nzoLogic

+0

@nzoLogic我想你會在 –