2017-11-11 63 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>