Sharing data between components in React

12,330

Solution 1

You can use any publish/subscribe events library and then make your components listen to any event you need.

For example:

import React from 'react'
import 'events' from 'eventPublishSubscribeLibrary'

class Component2 extends React.Component {
  constructor (props) {
    super(props)
    this.toggleVisibility = this.toogleVisibility.bind(this)
    this.state = {
      visible = true
    }
  }
  componentDidMount () {
    events.subscribe('clicked-button', this.toogleVisibility)
  }
  toogleVisibility () {
    this.setState({
      visible: !this.state.visible
    })
  }
  render () {
    return visible && (
      <div>content</div>
    )
  }
}

const Component4 = () => (
  <button onClick={events.publish('clicked-button')}>Toggle Visibility</button>
)

You can find in this post by davidwalsh a simple implementation for a Pub/Sub JavaScript Object. Or you can search in npm for some other library.

the "right" way

This is the most simple implementation I can think of and for small projects it is a quick an easy solution that should work.

Anyway, as far as the project will grow a bit you will start to have a lot of actions/reactions between your components. With every new component you'll add it'll get more complicated to track all of these relations between all your components. Here is where it comes handy to have the global state of your application stored in one single place, and that is one of the three principles that redux is based on: the single source of truth.

Solution 2

I think it's perfect time for you to introduce some state to your app. Try Redux, it's awesome.

Share:
12,330

Related videos on Youtube

luk_z
Author by

luk_z

currently front end web developer Meteor + React + Redux

Updated on September 28, 2022

Comments

  • luk_z
    luk_z over 1 year

    I'm developing an app using Meteor and React as view engine

    Consider this diagram:

    React hide component from another example

    I need to change C2 component state when C4 button click event is fired. Since they don't have a direct relationship i cannot access to C2 state directly from C4.

    Another example would be submit a form from a Component and get the data (value of input fields) declared in another Component.

    I know there are some possible hacks to solve this problem (e.g. Meteor Session, pass data through each component, flux-based Action/Dispatcher).

    React docs recommends to use event/subscribe system (flux is a possible solution, but flux is much more that this...) Communicate Between Components

    Redux is another possibility (i'm a bit worried about the fact that for large applications if i have a lot of actions, the combined-reducers-function will explode and also about the absence of an action-specific subscribe system - as far as i know all the listener will be executed when dispatch an action - i'm new in redux maybe i'm wrong)

    Flux or Redux are valid pattern and satisfy a need bigger than mine, i have already Meteor for that kind of work. My only need is to access the component state inside another...

    I need a scalable solution for medium/large applications with a high number of component views

    What's the "right" way to solve that problem?


    Update:

    recently I gave redux a chance and it seems to do the work (it is really awesome and well supported), so if you are in the same situations check React + Redux: submit multi-component form

  • luk_z
    luk_z almost 8 years
    Should you explain me how do you think to handle "Another example would be submit a form from a Component and get the data (value of input fields) declared in another Component." with redux?
  • luk_z
    luk_z almost 8 years
    Yeah, you are right, for large application redux give you more control and a unique global state can give you a powerful test tool. I'm a bit afraid it is not possible to subscribe functions on a particular action, but the subscription is made on the dispatcher.
  • luk_z
    luk_z almost 8 years
    ...and even... if the state of single reducer becomes complex (and in large applications, probably, it will be, or maybe you have a lot of small reducers...) the update process will be tortuous and an update on a state three leaf will clone the entire object sub-three
  • Eloy Pineda
    Eloy Pineda almost 8 years
    What do you mean with "I'm a bit afraid it is not possible to subscribe functions on a particular action"? With redux you don't have to subscribe to any events. You have container components that are connected to the redux state and dispatch actions. Any other component child of this containers are simply presentational and they don't know anything about redux. It is better explained in redux docs: Presentational and Container Components
  • Eloy Pineda
    Eloy Pineda almost 8 years
    To organize the reducers in large applications you divide them in multiple files. For example: reducers/users.js, reducers/products.js, etc. This is always gonna be more easy to maintain that tons of publishing/subscribing spread over all your components.
  • luk_z
    luk_z almost 8 years
    I think Redux is perfect to manage app state and "small reducer" it's a good solution.
  • luk_z
    luk_z almost 8 years
    The Form example above is a good test case. Since the reducer cannot execute impure functions and the container component that submit to database cannot access to the input fields (they are in other components), i have to -> bind the form input fields to the app state -> on Submit update/read the state -> update database with the input fields from the app state. The point is IMO the input fields should not be part of the app state (they aren't part of the application logic), and for this reason subscribe to an action should be a good feature in this case (obviously not in all situations).
  • luk_z
    luk_z almost 8 years
    The point is to get data from other components i need to bind it to the application state and It is not designed for this purpose. The app state should contain only logical information and the local ui data (e.g. form input fields value/state) should be stored inside components else you end up with a "dirty" application state.