GuerillaRadio
GuerillaRadio

Reputation: 1297

Use child component function to pass data to redux store via parent component/container

I'm new to React & Redux so it is difficult for me to explain in plain English but I'll try my best. I have a parent/container component that forms the main 'page' of my app. In this component I am rendering a header and various fields like so:

enter image description here

What I want to achieve is for any user input in the title field to be reflected where it currently says 'Untitled Practice' in the header.

The parent component looks like this (excluding various imports for brevity):

export class DrillCreator extends Component {
  render() {
    return (
      <div>
        <EditHeader />

        <div className="container-fluid max-width-container">
          <InputWithTooltip
            type={'text'}
            placeholderText={'Title'}
            tooltipText={'Title Tooltip'}
            required
          />

          <InputWithTooltip
            type={'textarea'}
            placeholderText={'Summary'}
            tooltipText={'Summary Tooltip'}
          />

          <InputWithTooltip
            type={'file'}
            placeholderText={'Hero Image/Video'}
            tooltipText={'Hero Image/Video Tooltip'}
          />

          <InputWithTooltip
            type={'select'}
            options={['7', '8', '9', '10']}
            placeholderText={'Ages'}
            tooltipText={'Ages Tooltip'}
            required
          />
        </div>
      </div>
    );
  }
}

The <InputWithTooltip /> component is essentially a container that renders the appropriate input along with a tooltip component:

export default class InputWithTooltip extends Component {
  constructor(props) {
    super(props);
    this.state = {
      textEntered: '',
    };
  }

  render() {
    let input = null;
    if (this.props.type === 'text') {
      input = (
        <TextInput
          placeholderText={this.props.placeholderText}
          updateText={textEntered => this.setState({ textEntered })}
        />
      );
    } else if (this.props.type === 'select') {
      input = (
        <SelectInput
          placeholderText={this.props.placeholderText}
          updateText={textEntered => this.setState({ textEntered })}
        />
      );
    } else if (this.props.type === 'textarea') {
      input = (
        <TextAreaInput
          placeholderText={this.props.placeholderText}
          updateText={textEntered => this.setState({ textEntered })}
        />
      );
    } else if (this.props.type === 'file') {
      input = (
        <FileInput
          placeholderText={this.props.placeholderText}
          updateText={textEntered => this.setState({ textEntered })}
        />
      );
    }

    return (
      <div>
        <InputTooltip tooltipText={this.props.tooltipText} />
        {input}
      </div>
    );
  }
}

As you can see, I have a textEntered state which is updated via an onChange function passed via the updateText props.

I have set up Redux so that I am able to call a dispatch function to set the title field in my reducer. This works fine if I simplify my parent component and simply call the <TextInput /> component which has the updateText prop:

export class DrillCreator extends Component {
  constructor() {
    super();
    this.state = {
      textEntered: '',
    };
  }

  render() {
    return (
      <TextInput
        placeholderText="Title"
        updateText={(textEntered) => {
          this.setState({ textEntered });
          this.props.setDrillTitleAction({ textEntered });
        }}
      />
    );
  }
}

const mapDispatchToProps = dispatch => ({
  setDrillTitleAction: drillCreator => dispatch(setDrillTitle(drillCreator)),
});

export default connect(null, mapDispatchToProps)(DrillCreator);

The issue I have is that I want to call setDrillTitleAction from <InputWithTooltip /> instead of <TextInput /> as this is the only field in the form that I want to do anything special with.

Like I said I'm new to React and Redux so could be massively overcomplicating something or completely missing the point so any pointers would be massively helpful. Thanks.

Upvotes: 0

Views: 910

Answers (1)

Phil Bellamy
Phil Bellamy

Reputation: 330

You can pass the dispatch function from the container component in as a prop to the display component, and then call it when the value is changed.

In your case you need to pass setTitleDrillAction in as a prop to InputWithTooltip and then call if from within your updateText callbacks.

One thing to point out is that you will be storing the text box value multiple times - on the redux state and the InputWithTooltip state. You might choose to just make InputWithTooltip a stateless component which receives its value as a prop and dispatches updates to redux (via its parent container as described above).

Upvotes: 2

Related Questions