Matt
Matt

Reputation: 79

React: parent component props in child without passing explicitly

Is it possible to have the props of the parent component to be available in child component without passing them down?

I am trying to implement a provider pattern, so that to access all the provider props in its child components. EX:

Suppose the below provider comp FetchProvider will fetch the data and theme props on its own, and when any child component is enclosed by it, I want to access both props "data" and "theme" in the child component as well. How can we achieve it?

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
   }
}

and if I try to above components as below.

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

Upvotes: 6

Views: 4507

Answers (4)

Shubham Khatri
Shubham Khatri

Reputation: 281686

Your use case can be solved with the usage of React context. With the help of Context, any child that is wrapped by a provided can be a consumer for the data that is provided by the Provider

In your case, you can use it like

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};
   }
}

ChildComponent.js

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>
)

However given the fact that you are already using Redux, which is build on the concept of Context, you might as well use redux and access the values within the child component since they are the same values that are supplied from the Redux store to the child by parent.

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
     }
}

Upvotes: 1

Sagiv b.g
Sagiv b.g

Reputation: 31024

This is exactly what react context is all about.

A Consumer can access data the a Provider exposes no matter how deeply nested it is.

// 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>
  );
}

Here is a small running example:

Note This is the react v16 context API.

Upvotes: 3

bmovement
bmovement

Reputation: 867

Are you looking for:

class MyParent extends Component {
    render() {
        return <MyChild {...this.props}>
            // child components
        </MyChild>
    }
}

This would pass all of the props passed into MyParent to the MyChild being rendered.

Upvotes: 0

Ray
Ray

Reputation: 9674

You can use React.Children to iterate over the children and pass whatever props you want to send to the new cloned elements using React.cloneElement.

EX:

class Parent extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    const { children } = this.props;
    const newChildren = React.Children.map(children, child =>
      React.cloneElement(child, { myProp: 'test' }));

    return(
      <View>
        {newChildren}
      </View>
    )
  }
}

Upvotes: 0

Related Questions