Italo Borges
Italo Borges

Reputation: 2554

How to customize requests inside a React component

I have a component ContentHeader that I will use in almost each content, it provides a header with title and two buttons, New and Search.

import React from 'react';
import Title from 'components/Title';
import BtnSearch from 'components/BtnSearch';
import BtnNew from 'components/BtnNew';

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

  render () {
    return (
      <div className='content-header'>
        <Title name={this.props.title} />

        <ul className='actions'>
          <li className='action-item'>
            <BtnSearch />
          </li>
          <li className='action-item'>
            <BtnNew />
          </li>
        </ul>
      </div>
    );
  }
}

export default ContentHeader;

The button components that I use inside the ContentHeader:

// Component Button Search
import React from 'react';
import { NavLink } from 'react-router-dom';

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

  render () {
    return (
      <a className='btn-actions btn-search' onClick=CUSTOM_REQUEST>
        <span className="icon-center"></span>
      </a>
    )
  }
}

export default BtnSearch;


// Component Button New
import React from 'react';
import { NavLink } from 'react-router-dom';

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

  render () {
    return (
      <NavLink to=CUSTOM_REQUEST className='btn-actions btn-new'>
        <span className="icon-center"></span>
      </NavLink>
    )
  }
}

export default BtnNew;

Let's say that I will have Projects, Contracts and Widgets main contents and I need to use the ContentHeader inside.

For each main content I will have a different title label, which I can pass by props, since is just one level deep. But also, I will have different requests for each button inside the ContentHeader component, related to the main content that it belongs.

So, how can I pass these different requests to the buttons related to my main content? Props as well? What about if I have a deeper component tree?

PS: As an example I used NavLink and a simple onClick inside my button components with a flag CUSTOM_REQUEST

Thanks!

Upvotes: 1

Views: 93

Answers (2)

simbathesailor
simbathesailor

Reputation: 3687

If you are using plain react and nesting is too large, then it will become very difficult to pass props to every level . In that case you can use context API from react.

You can read it here : how-to-use-context

But it is not encouraged to use context.

You can read it here: why not to use context

You can try the following approach

function Wrapper(newBtnAction, searchBtnAction, label, props) {
  return ( < ContentHeader {...props
    }
    label = {
      label
    }
    newBtnAction = {
      newBtnAction
    }
    searchBtnAction = {
      searchBtnAction
    }
    />
  )
}

Now you can use the wrapped component anywhere just you need to pass proper function bind with store.dispatch

Lets say you have a component B ,C, D, E you can use it like this

class B extends React.Component {

  render() {
    // get proper actions here
    const {
      newBtnAction,
      searchBtnAction,
      label
    } = this.props
    return ( < C >
      < D >
      < E > {
        Wrapper(newBtnAction, searchBtnAction, label, this.props)
      } < /E> < /D> < /C>
    )
  }
}

we call this concept as higher order components in react. This is basically a design pattern that comes out of react component approach

Note: Mind brackets, not executed the code

Upvotes: 1

Oyvind Andersson
Oyvind Andersson

Reputation: 362

If I understand your question correctly, you need to be able to pass a specific request to the respective ContentHeader component based on the type of content.

You can definitely just pass that request function via props to the child button of that page/content component.

import React from 'react';
import Title from 'components/Title';
import BtnSearch from 'components/BtnSearch';
import BtnNew from 'components/BtnNew';

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

  render () {
    const { myRequestFunc } = this.props
    //...or if not es15
    var myRequestFunc = this.props.myRequestFunc

    return (
      <div className='content-header'>
        <Title name={this.props.title} />

        <ul className='actions'>
          <li className='action-item'>
            <BtnSearch />
          </li>
          <li className='action-item'>
            <BtnNew requestFunc={myRequestFunc} />
          </li>
        </ul>
      </div>
    );
  }
}

export default ContentHeader;

That is the easy way, anyhow. You could - depending on the size of your application - explore Redux, React-Redux and Redux-Thunk or Redux-Saga to avoid the inevitable passing of props down several levels. Checkout using redux with react

Upvotes: 1

Related Questions