2017-03-24 27 views
0

所以,我有一個網站與反應路由器和終極版(下面的例子是嚴重簡化)爲什麼我會得到使用反應路由器和嵌套組件

<Route path="/" component={ A } > 
    <Route path="/B" component={B} /> 
</Route> 

A.jsx

失敗道具類型
class A extends Component { 
    render() { 
     const calculated_value_to_pass_down = FooBar() 
     return (
      <div> 
       {React.Children.map(this.props.children, 
        (child) => React.cloneElement(child, { 
         required_prop: calculated_value_to_pass_down 
        }) 
       )} 
      </div> 
     ) 
    } 
}  
export default A 

B.jsx

class B extends Component { 
    render() { 
     return (
      <div> 
       { this.props.required_prop } 
      </div> 
     ) 
    } 
}  
B.propTypes = { 
    required_prop: PropTypes.any.isRequired 
}  
export default B 

但是,當我去localhost:8080/B我得到一個錯誤回溯:

Warning: Failed prop type: The prop `required_prop` is marked as required in `B`, but its value is `undefined`. 
in A (created by RouterContext) 
in RouterContext (created by Router) 
in Router 
in Provider 

的100頁%的作品。這個錯誤在生產中不會發生,但我討厭顯示出來的錯誤。

頁面從來沒有真正使用未定義的道具進行渲染,甚至在渲染被調用之前我得到錯誤。

我知道我可以簡單地刪除.isRequired,它會工作,但這個想法聞起來很爛。

謝謝!

+1

你在哪裏傳遞道具成分B? –

+1

'calculated_value_to_pass_down'未定義? @MayankShukla裏面'React.cloneElement'我相信 – DroidNoob

+0

當我做'console.log(this.props.required_prop)'上的B.jsx的render方法我總是得到一個值,從來沒有'undefined' –

回答

1

我嘗試了很多方法,但沒有得到這個警告的原因。有一件事我可以猜測,但不敢肯定,每DOCcloneElement爲:

克隆並返回一個新元素使用作爲出發點 元素做出反應。由此產生的元素將具有原始元素的道具 ,並且淺層合併新道具。新的兒童將取代現有的兒童 。

cloneElement複製現有的元素,可能是該組件先創建而沒有道具然後被複制。

臨時解決是,你可以使用defaultProps定義prop的默認值,這樣做也不會拋出警告,就像這樣:

B.defaultProps = { 
    required_prop: '' 
} 
+1

啊,你的意見讓我失望了:https://github.com/ReactTraining/react-router/issues/1857#issuecomment-180879045,似乎沒有完美的方式去做我正在做的事情。 –

0

它沒有出現在生產中,因爲這些警告在生產中沒有顯示/使用,但仍然存在錯誤。 (propTypes從產品代碼中刪除)

問題是A.jsx甚至在FooBar()完成之前渲染B.jsx,這意味着它發送的calculate_value_to_pass_down的值最初是未定義的,並且如果您的B.jsx組件如果calculate_value_to_pass_down不是未定義的,如果未定義則不呈現B.jsx組件,則解決方案將不會檢查A.jsx。

<div> 
    {calculated_value_to_pass_down!==undefined? React.Children.map(this.props.children, 
    (child) => React.cloneElement(child, { 
     required_prop: calculated_value_to_pass_down 
     }) 
    ) : <div>LOADING</div>} 
</div> 
+0

有人懷疑,他在return之前調用'function',所以'A '在'FooBar()'之前渲染'B'? –

+0

DOM不會在計算完成後等待呈現,一旦計算完成,它只會適當更新,但它永遠不會等待它 –

+1

我認爲,這不是問題,我只是在本地運行該代碼, const calculated_value_to_pass_down ='abc'',仍然得到相同的錯誤:) –

0

感謝@ malayank - 舒克拉的答案我意識到問題出在React.cloneElement部分的代碼中。

有一個在更多的討論:ReactTraining's Github Issues

看來解決方案是:

  1. 從PropTypes刪除.isRequired從PropTypes
  2. 設置默認值
  3. 在包裝組件
  4. 裹子組件設置道具默認情況下,直到適當的道具發送(如果您使用B.jsx多個地方,並不想刪除PropType使用無處不在
  5. React-Router v4有一個選項,允許您在路由上編寫渲染屬性,而不是組件屬性;但對我的情況不起作用;或者我不正確地理解它?

    <Route 
        exact 
        path="/b" 
        render={routeProps => <B {...props} {...routeProps} />} 
    /> 
    

我期待着任何其他的答案