2017-11-11 66 views
0

我有一個主文檔通過從主要成分之外的功能:如何使用做出反應,終極版的提供商

<script> 
    function fnc (param) { 
     alert(param); 
    } 
    ReactDOM.render(
     <Provider store={store}> 
      <App fnc={fnc}/> 
     </Provider>, 
     document.getElementById('root') 
    ); 
</script> 

應用組件有了孩子和孫子。有沒有更好的方法將fnc傳遞給孫子們(也許通過連接來獲得它,類似於減速器映射到道具),所以它可以從那裏調用,而不是通過所有級別的所有嵌套組件傳遞它作爲道具(應用程序 - >兒童 - >孫輩)?

+0

高階組件[鏈接](https://reactjs.org/docs/higher-order-components.html)可能會幫助你。 – mersocarlin

回答

1

React's context feature可用於這樣的事情。實際上,react-redux用於將商店從Provider轉換爲connect函數。

處理上下文時,通常最好與react-redux類似,使用提供程序組件添加它,並使用higher-order component (HOC)來訪問它。

提供者:

import React from 'react'; 
import propTypes from 'prop-types'; 

class FunctionProvider extends React.Component { 
    getChildContext() { 
    return { 
     fnc: this.props.fnc 
    }; 
    } 

    render() { 
    return React.Children.only(this.props.children); 
    } 
} 

FunctionProvider.childContextTypes = { 
    fnc: propTypes.func 
}; 

HOC:

import React from 'react'; 
import propTypes from 'prop-types'; 

function withFnc(WrappedComponent) { 
    class WithFnc extend React.Component { 
    render() { 
     return < WrappedComponent fnc={this.context.fnc} {...props} /> 
    } 

    WithFnc.contextTypes = = { 
    fnc: propTypes.func 
    }; 

    return WithFnc 
} 

添加FncProvider

function fnc (param) { 
    alert(param); 
} 

ReactDOM.render(
    <Provider store={store}> 
    <FncProvider fnc={fnc}> 
     <App /> 
    </FncProvider> 
    </Provider>, 
    document.getElementById('root') 
); 

裹組件:

import React from 'react'; 

class MyComponent extends React.Component { 
    render() { 
    return <button onClick={() => this.props.fnc('test')}>Click Me!</button> 
    } 
} 

export connect(mapStateToProps)(withFnc(MyComponent) 

這可能有點過分,但如果你只需要將它傳遞一層或兩層以及一些組件。有時props是一個完美的解決方案。

如果您特別想使用redux來解決這個問題,您可以創建一箇中間件,在特定操作上調用fnc(我將使用ES6語法,因爲它的方式更乾淨,但讓我知道是否需要它是瀏覽器兼容的,我會補充說太):

const fncMiddleware = (fnc) => (store) => (next) => (action) => { 
    if (action.type === 'CALL_FNC') { 
    fnc(action.param); 
    } 
    return next(action); 
} 

的包括中間件,當您創建存儲:

function fnc (param) { 
    alert(param); 
} 

var store = createStore(reducer, applyMiddleware(fncMiddleware(fnc))); 

ReactDOM.render(
    <Provider store={store}> 
    <App /> 
    </Provider>, 
    document.getElementById('root') 
); 

現在你可以從像任何你連接的部件派遣像{ type: 'CALL_FNC', param='test' }行動其他活動ñ。

+0

謝謝!我喜歡中間件的方法,適合lika的魅力! –

0

終極版的connect是一個簡單的Higher Order Function增強注入終極版的狀態到道具您的組件(mapStateToProps是它的一個例子)。

您可以使用相同的方法將func僅傳遞給特定組件。

const withCustomFunctionHOC = WrappedComponent => { 
 
    const yourCustomFunction =() => alert('it works!') 
 
    
 
    return (props) => 
 
    <WrappedComponent 
 
     {...props} 
 
     yourCustomFunction={yourCustomFunction} 
 
    /> 
 
} 
 

 
const ChildComponent = ({ a, b, yourCustomFunction }) => 
 
    <div style={{ marginTop: 20, marginBottom: 20 }}> 
 
    ChildComponent 
 
    <div>Prop a: {a}</div> 
 
    <div>Prop b: {b}</div> 
 
    {yourCustomFunction 
 
     ? <button onClick={yourCustomFunction}>I have customFunction (click me)</button> 
 
     : <div>I don't have customFunction</div> 
 
    } 
 
    </div> 
 

 
const EnhancedChildComponent = withCustomFunctionHOC(ChildComponent) 
 
const App =() => 
 
    <div> 
 
    <ChildComponent a={1} b={2} /> 
 
    <EnhancedChildComponent a={3} b={4} /> 
 
    </div> 
 

 
ReactDOM.render(
 
    <App />, 
 
    document.getElementById('root') 
 
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 
<div id="root"></div>