如何使用react-redux的Provider从主组件外部传递一个函数

时间:2017-11-11 12:01:36

标签: reactjs redux react-redux

我有一份主要文件:

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

App组件有子女和孙子女。是否有更好的方法将fnc传递给孙子(也许通过连接获取它,类似于reducers如何映射到props),因此可以从那里调用它,而不是通过所有级别的所有嵌套组件将其作为prop传递(App - &gt;孩子 - &gt;孙子女?)

2 个答案:

答案 0 :(得分: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' }之类的操作。

答案 1 :(得分:0)

Redux的connect只是一个Higher Order Function,通过将redux的状态注入道具来增强你的组件( mapStateToProps 就是它的一个例子)

您可以使用相同的方法将func仅传递给您希望的特定组件。

&#13;
&#13;
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')
)
&#13;
<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>
&#13;
&#13;
&#13;