stiMULAnt
stiMULAnt

Reputation: 111

How to pass a state to multiple other classes in React

I started learning React approx. month ago and I'm very confused about the concept because its still something new to me(compared to my previous work in C++ and C).

To quickly summarize I would like to know what is React's equivalent of C++ return form a function. How would I return value(or values) from a function(in my case class functions/states) and use it in my other components.

I have made an simple script that changes background to simulate RGB light on mouse and I made it so the HSL color mode is applied to the background of the component. I would like to use this on multiple components,icons, etc on my page but it feels like there is a better way than importing all functions in three files making the work triple than requiered.

import React, { Component } from 'react'
import './colorStrip.scss'


class ColorStrip extends Component {

    constructor(props) {
        super(props)

        this.colorHue=10;
        this.colorSaturation=100;
        this.colorLightness=50;

        this.state = {
            color:"hsl(0,100%,50%)"
        }

        this.changeColor(1);
    } 


    changeColor = (speed) => {

        this.colorHue+=10*speed;

        if(this.colorHue>=360)
            this.colorHue=0;

        this.setState({ 
            color : "hsl("+this.colorHue+","+this.colorSaturation+"%,"+this.colorLightness+"%)"
        })


        setTimeout(() => {this.changeColor(speed)},75)
    }



    render() {
        return (
            <svg style={{backgroundColor:this.state.color}} className="strip">
            </svg>

        )
    }
}

export default ColorStrip

So I would like to use this.state.color(or this.state.colorHue or any state) in three other SVG components on my page.

I really looked some of the other answers but they were quite complex and requiered multiple returns which was confusing.

Upvotes: 1

Views: 1615

Answers (4)

Henry Woody
Henry Woody

Reputation: 15662

I'd suggest creating a Higher-Order Component (HOC) to house the color logic and then you can wrap any component you want with this HOC and the wrapped component will have the logic & data you need.

For example:

import React, { Component } from "react";

function withColor(WrappedComponent) {
    return class ComponentWithColor extends Component {
        constructor(props) {
            super(props);

            this.colorHue=10;
            this.colorSaturation=100;
            this.colorLightness=50;

            this.state = {
                color:"hsl(0,100%,50%)"
            }

            this.changeColor(1);
        }

        changeColor = (speed) => {

            this.colorHue+=10*speed;

            if(this.colorHue>=360)
                this.colorHue=0;

            this.setState({ 
                color : "hsl("+this.colorHue+","+this.colorSaturation+"%,"+this.colorLightness+"%)"
            })


            setTimeout(() => {this.changeColor(speed)},75)
        }

        render() {
            const { color } = this.state;
            return <WrappedComponent color={ color } { ...this.props }/>
        }
    }
}

Then if you define a new component, and you want it to have access to the color prop, just wrap the component class/function in withColor before constructing.

For example:

class MyComponent extends Component {
    render() {
        const { color } = this.props;

        return (
            <svg style={backgroundColor:color} className="strip">
            </svg>
        )
    }
}

const MyComponentWithColor = withColor(MyComponent);
// then export & use MyComponentWithColor

Upvotes: 0

Arthur Serafim
Arthur Serafim

Reputation: 423

As Jonathan said, you can pass state as props to other components, but only if they are connected. If the svgs you are using are not being rendered in the same file, things will become a little messy. In order to 'fix' this, people use state management tools, such as redux and context API.

Redux, for example, is built based on database design, so you can access the state globally. Tough it is really useful, the environment is not beginners friendly, and I do not advise you learning it until completely grasping react.

Upvotes: 1

Jonathan Beadle
Jonathan Beadle

Reputation: 418

There are a couple different options you can use to achieve this. One would be to move your function that calculates the colour to a higher level component (so one of the parent components), that has the child components you want to pass this state to, and then pass your state down through component props.

class parent extends component {
    // your functions to calculate your colour

    render () {
        return <div>
            <ChildComponent colourProp={this.state.color} />
            <ChildComponent colourProp={this.state.color} />
            <ChildComponent colourProp={this.state.color} />
        </div>
    }
}

Another option if you need the colour to change based on the child component, is to pass down the function that alters the colour to the child component. So similar to the example above, but you would pass down the colour changing function to the child as well.

<ChildComponent colourProp={this.state.color} changeColour={this.changeColourFunction}/>

Now you can call that function from your child

// Inside child component
this.props.changeColour(params)

And now your parent will change its state, and the new colour will get changed in the parent and passed down to all the children.

Lastly you can try using ReactContext, set it up in a file that's external to all your components and and import it to your components. In your parent component where you pass your initial state, you would use YourContext.Provider and pass your initial state. Then in your children you can use YourContext.Consumer. For more details on this see : https://reactjs.org/docs/context.html

Upvotes: 2

Diego P
Diego P

Reputation: 1758

Try this way:

import './colorStrip.scss'
class ColorStrip extends Component {
  constructor(props) {
    super(props)
    this.colorHue=10;
    this.colorSaturation=100;
    this.colorLightness=50;
    this.state = {
        color:"hsl(0,100%,50%)"
    }
    this.changeColor(1);
  } 
  changeColor = (speed) => {
    this.colorHue+=10*speed;
    if(this.colorHue>=360)
        this.colorHue=0;
    this.setState({ 
        color : "hsl("+this.colorHue+","+this.colorSaturation+"%,"+this.colorLightness+"%)"
    })
    setTimeout(() => {this.changeColor(speed)},75)
  }
  render() {
  const { color } = this.props;
    return (
        <svg style={backgroundColor:color} className="strip">
        </svg>
    )
  }
}
export default ColorStrip

Upvotes: 0

Related Questions