Javascript React:父组件在子组件中道具,而不显式传递

Javascript React:父组件在子组件中道具,而不显式传递,javascript,reactjs,Javascript,Reactjs,是否可以让父组件的道具在子组件中可用,而无需向下传递它们 我试图实现一个提供者模式,以便访问其子组件中的所有提供者道具。 例: 假设下面的提供者compFetchProvider将自己获取数据和主题道具,并且当任何子组件被它包围时,我希望访问子组件中的道具“数据”和“主题”。我们如何才能做到这一点 class FetchProvider { proptypes= { data: PropTypes.shape({}), theme: PropTypes.shape(

是否可以让父组件的道具在子组件中可用,而无需向下传递它们

我试图实现一个提供者模式,以便访问其子组件中的所有提供者道具。 例:

假设下面的提供者comp
FetchProvider
将自己获取数据和主题道具,并且当任何子组件被它包围时,我希望访问子组件中的道具“数据”和“主题”。我们如何才能做到这一点

class FetchProvider 
{

   proptypes= {
     data: PropTypes.shape({}),
     theme: PropTypes.shape({})
   }

   render()
   {
     // do some
   }

   mapStateToProps()
   {
      return {data, theme};
   }
}

class ChildComponent
{

   proptypes= {
     name: PropTypes.shape({})
   }

   render()
   {
     const{data, them} = this.props; // is this possible here?
     // do some
   }
}
如果我试着按照下面的方式来描述上面的组件

<FetchProvider>
   <ChildComponent name="some value"/>  //how can we access parent component props here? without passing them down
<FetchProvider/>

//我们如何在这里访问父组件道具?不传下去

您可以使用
React.Children
迭代子元素,并使用
React.cloneElement
将要发送的任何道具传递给新的克隆元素

例:

类父级扩展React.Component{
建造师(道具){
超级(道具);
}
render(){
const{children}=this.props;
const newChildren=React.Children.map(Children,child=>
cloneElement(child,{myProp:'test'});
返回(
{newChildren}
)
}
}
您正在寻找:

class MyParent extends Component {
    render() {
        return <MyChild {...this.props}>
            // child components
        </MyChild>
    }
}
类MyParent扩展组件{
render(){
返回
//子组件
}
}
这会将传递到
MyParent
的所有道具传递给正在呈现的
MyChild

这正是全部内容

消费者
可以访问
提供者
公开的数据,无论其嵌套有多深

// Context lets us pass a value deep into the component tree
// without explicitly threading it through every component.
// Create a context for the current theme (with "light" as the default).
const ThemeContext = React.createContext('light');

class App extends React.Component {
  render() {
    // Use a Provider to pass the current theme to the tree below.
    // Any component can read it, no matter how deep it is.
    // In this example, we're passing "dark" as the current value.
    return (
      <ThemeContext.Provider value="dark">

<Toolbar />
      </ThemeContext.Provider>
    );
  }
}

// A component in the middle doesn't have to
// pass the theme down explicitly anymore.
function Toolbar(props) {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

function ThemedButton(props) {
  // Use a Consumer to read the current theme context.
  // React will find the closest theme Provider above and use its value.
  // In this example, the current theme is "dark".
  return (
    <ThemeContext.Consumer>

{theme => <Button {...props} theme={theme} />}
    </ThemeContext.Consumer>
  );
}
//上下文允许我们将值传递到组件树的深处
//没有显式地将其穿过每个组件。
//为当前主题创建上下文(默认为“light”)。
const ThemeContext=React.createContext('light');
类应用程序扩展了React.Component{
render(){
//使用提供程序将当前主题传递到下面的树。
//任何组件都可以读取它,无论它有多深。
//在本例中,我们将“暗”传递为当前值。
返回(
);
}
}
中间的组件不必
//再明确地传递主题。
功能工具栏(道具){
返回(
);
}
功能按钮(道具){
//使用使用者读取当前主题上下文。
//React将在上面找到最近的主题提供程序并使用其值。
//在本例中,当前主题为“暗”。
返回(
{主题=>}
);
}
下面是一个小例子:


注意这是react v16上下文API。

您的用例可以通过使用来解决。在上下文的帮助下,由提供者包装的任何子级都可以是提供者提供的数据的使用者

在你的情况下,你可以像这样使用它

context.js

export const FetchContext = React.createContext();
Provider.js

import { FetchContext } from 'path/to/context.js';
class FetchProvider extends React.Component
{

   proptypes= {
     data: PropTypes.shape({}),
     theme: PropTypes.shape({})
   }

   render()
   {
        const { data, theme, children } = this.props;
        return (
             <FetchContext.Provider value={{ data, theme}}>
                   {children}
             </FetchContext.Provider>
        )
   }

   mapStateToProps()
   {
      return {data, theme};
   }
}

无论如何,您都在将prop“myProp”从父级传递给子级。我在父级即FetchProvider中使用了类似的React上下文概念,使用了ChildContextTypes和getChildContext函数。并使用HOC装饰器将上下文值向下注入到子级。以这种方式使用React上下文似乎非常干净。@Matt,这是React中提供的新上下文API,从版本16.3.0开始提供。如果您使用的react版本高于此版本,则应以这种方式使用上下文。
import { FetchContext } from 'path/to/context.js';
class FetchProvider extends React.Component
{

   proptypes= {
     data: PropTypes.shape({}),
     theme: PropTypes.shape({})
   }

   render()
   {
        const { data, theme, children } = this.props;
        return (
             <FetchContext.Provider value={{ data, theme}}>
                   {children}
             </FetchContext.Provider>
        )
   }

   mapStateToProps()
   {
      return {data, theme};
   }
}
class ChildComponent extends React.Component
{

   proptypes= {
     name: PropTypes.shape({})
   }

   render()
   {
     const{data, them} = this.props; // use it from props here
     // do some
   }
}

export default (props) => (
     <FetchContext.Consumer>
           {({ data, theme }) => <ChildComponent {...props} data={data} theme={theme} />}
     </FetchContext.Consumer>
)
class ChildComponent extends React.Component
{

   proptypes= {
     name: PropTypes.shape({})
   }

   render()
   {
     const{data, them} = this.props; // use it from props here
     // do some
   }
}

const mapStateToProps = (state) => {
     return {
          data: state.data,
          theme: state.theme
     }
}