Share volatile variable between React Components [duplicate] - javascript

This question already has answers here:
How can I communicate between related react components?
(11 answers)
Closed 3 years ago.
I have a group of Components that render different parts of the same page. Whenever an action is commited inside one of them, the other ones should be locked (a volatile flag should be propagated through them and trigger a javascript function that disables all elements)
Block Components:
class FirstBlock extends React.Component {
constructor(props) {
super(props);
.......
}
}
render() {......}
}
class SecondBlock extends React.Component {
constructor(props) {
super(props);
.......
}
}
render() {......}
}
Page Component:
import FirstBlock from 'Components/FirstBlock';
import SecondBlock from 'Components/SecondBlock';
class PageBlock extends React.Component {
constructor(props) {
super(props);
.......
}
}
render() {
return (
<FirstBlock ... />
<SecondBlock ... />
);
}
}
Any ideas? I'm new to react and any tip will be helpful.

In (very) general terms, pass an event handler into each of your blocks from your parent. When an action is triggered from one of them, deal with this in the parent. If you need to change your behaviour depending on which child raises the action you'll need to have some kind of identifier for each of your children, so that when the handler is called it knows what to do.
class PageBlock extends React.Component {
constructor(props) {
super(props);
.......
}
}
onAction = (id)=>{
// set isVolatile or do whatever you need to do
}
render() {
return (
<FirstBlock id={firstBlockId} onAction={this.onAction}... />
<SecondBlock id={secondBlockId} onAction={this.onAction}... />
);
}
}
class FirstBlock extends React.Component {
constructor(props) {
super(props);
.......
}
}
onAction = ()=>{
this.props.onAction(this.props.id)
}
render() {......}
}
The principle is to lift your common state (i.e. that something has triggered an action) up to a parent so that the children that need to know about the state can have access to it.

Related

React: how to fire the parent component method?

How do I get access from component to the methods of the owner of this component?
I.e. (maybe) you need to get a pointer to the owner of the element and already call the method by the pointer.
For example:
component #1
class MyReport extends Component {
my_method() {}
render() {
return (
<MyReport>
<MyElement />
</MyReport>
);
}
}
and component #2
class MyElement extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(event) {
// GET METHOD my_method OF OWNER
console.log(parent.my_method());
}
render() {
return <Button onClick={this.handleClick}>Press</Button>;
}
}
If you are looking how to call a method of the parent you just pass it trough props of the child component:
Component #1
class MyReport extends Component {
my_method() {
}
render() {
return (
<MyReport>
<MyElement methodFromParent={this.my_method}/>
</MyReport>
);
}
}
Component #2
class MyElement extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(event) {
// GET METHOD my_method OF OWNER
console.log(this.props.methodFromParent);
}
render() {
return (
<Button onClick={this.handleClick}>Press</Button>
);
}
}
Although, you wrapping MyElement with MyReport seems like a mistake you made when writing this question.

How to pass variables from class to class

Alright, so I'm trying to simplify a project I'm working on, but of all the information I've read on the internet, none of it has answered my question. My doubt is how can I pass variables (the name of the variable, and its value) from one class to another class? Should I use props? Should I just do something similar to this.state.variable? How can it be done? I'll write a sample code just to show what I'm trying to do more visually, however, this is not my actual code. Thanks for helping :)
class FishInSea{
constructor(props){
super(props);
this.setState({fishInSea: 100});
}
render(){
return(
<div>Fish in the sea: {this.state.fishInSea}</div>
);
}
}
class FishInOcean{
constructor(props){
super(props);
this.setState({fishInOcean: <FishInSea this.props.fishInSea/> * 1000});
}
render(){
return(
<div>Fish in the ocean: {this.state.fishInOcean}</div>
);
}
}
export default FishInOcean;
You need to first make both the classes in to React components. Since both the classes modify the state so they called as statefull components. The class has to extend the Base class of React i.e., Component.
in constructor we only do state initialisations but won’t modify the state there. But you are modifying the state which isn’t correct. Instead move setState to componentDidMount.
Say suppose in FishInSea class you have fishInSea and you want to pass it to FishInOcean component as props.
Check below two corrected components how they are passed from one component to the other
import React, { Component } from “react”;
class FishInSea extends Component{
constructor(props){
super(props);
this.state = {
fishInSea: 100
}
}
componentDidMount(){
this.setState({fishInSea: 100});
}
render(){
const { fishInSea } = this.state;
return(
<div>Fish in the sea:
<FishInOcean fishInSea={fishInSea} />
</div>
);
}
}
import React, { Component } from “react”;
class FishInOcean extends Component{
constructor(props){
super(props);
this.state = {fishInOcean: 1000}
}
componentDidMount(){
this.setState({fishInOcean: 1000});
}
render(){
const { fishInOcean} = this.state;
const { fishInSea } = this.props;
return(
<div>Fish in the ocean: {fishInOcean}
{fishInSea}
</div>
);
}
}
export default FishInOcean;
/*There was a typo*/

this.state vs state in React

I'm working in a new codebase. Normally, I would set up state like this in a React component:
class App extends React.Component {
constructor() {
super();
this.state={
foo: 'bar'
}
}
....
In this new codebase, I'm seeing a lot of this:
class App extends React.Component {
state={
foo: 'bar'
}
....
Is there an advantage to doing it this way? They seem to only do it when state doesn't need to be altered. I always thought of state as being something React handled. Is this an ok thing to do?
The end result of both approaches is the same. Both approaches are just setting the initial state of the component. It's worth noting that class properties are a stage 3 proposal, so all development environments may not be able to use them.
I personally like to use the class field variant if nothing else is done in the constructor, as it is less code to write, and you have no super call to worry about.
Example
class Component1 extends React.Component {
state = { value: this.props.initialValue };
render() {
return <div> {this.state.value} </div>
}
}
class Component2 extends React.Component {
constructor(props) {
super(props);
this.state = { value: props.initialValue };
}
render() {
return <div> {this.state.value} </div>
}
}
function App() {
return (
<div>
<Component1 initialValue={1} />
<Component2 initialValue={2} />
</div>
);
}
Actually both of them bind to this pointer. the this that made in constructor of class.
Totally you can access to local state by this.state but in first style you can pass props to constructor by super and then use it in state declaration, just like below:
class App extends React.Component {
constructor(props) {
super(props);
this.state={
foo: 'bar',
jaz: props.someParentState,
}
}
....
Awesome, you can access to props in constructor, isn't pretty? I definitely use this style for local state declaration.
Hope this helps you.

Transferring State Between Components - React

If I have a state in the App class, and I want to transfer those values into SecondApp, how do you go about that? I've tried using props but when I console log it, I get undefined.
Excuse the nooby question, I'm fairly new and trying to get my hands dirty, haha.
class App extends Component {
constructor(props) {
super(props)
this.state = {
todo: ['hello', 'hey']
}
}
}
class SecondApp extends Component {
render() {
return (
<p>?</p>
)
}
}
If you are passing the props correctly, they shouldn't turn up undefined. Props would be the correct way to go about this though!
class App extends Component {
constructor(props) {
super(props)
this.state = {
todo: ['hello', 'hey']
}
}
render() {
return <SecondApp testProp={this.state.todo}/>;
}
}
class SecondApp extends Component {
render() {
return <div>this is the prop: {this.props.testProp}</div>;
}
}
If you pass it through like that, you'll see the prop show up as "hellohey", check out the JSFiddle. Next off you'll likely want to render these items in a list, and will need to handle that accordingly. This article will point you in the right direction!
First you need to call SecondApp in App and then pass props.
class SecondApp extends React.Component {
render() {
return ( <
p > {this.props.todo} < /p>
)
}
}
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
todo: ['hello', 'hey']
}
}
render() {
return ( <
SecondApp todo = {
this.state.todo
} />
);
}
}
ReactDOM.render(<App />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
If you mean to pass data from one app to another (that means, you render an app on an id and another app on another id) you can use events.
Whenever the state of the first app updates, you can dispatch an event and put an event listener on the other app, that updates it's state.
This is a common way to share data between independent modules/apps.
You can read more about this when you google "observer subscriber pattern".
Otherwise, if you mean to pass data to a child component, you really should read the react documentation.

Add methods to Higher Order Components in React

From what I understand, HOCs in ReactJS add props to your decorated component, but I want to add methods that can also act on the state.
As an example, I generally never call this.setState() without checking this.isMounted() first. In essence, I want:
export default ComposedComponent => class BaseComponent extends React.Component {
static displayName = "BaseComponent";
constructor(props) {
super(props);
}
//------> I want this method to be available to any ComposedComponent
//------> And it has to act upon the state of ComposedComponent
updateState(obj) {
if (this.isMounted() && obj) {
this.setState(obj);
}
}
render() {
return (
<ComposedComponent {...this.props} {...this.state} />
)
}
}
Say I want to decorate my component Home. So I'd just return it as export default BaseComponent(Home).
But this.updateState() is not available inside Home class. How do I solve this?
Okay, I figured it out. I had spent too much time on this, so I hope this answer could help somebody out as well. Short answer: add the method in your decorator to props, then bind it in your decorated class' constructor.
Here is the code:
export default ComposedComponent => class BaseComponent extends React.Component {
static displayName = "BaseComponent";
constructor(props) {
super(props);
// Note how I am adding this to state
// This will be passed as a prop to your composed component
this.state = {
updateState: this.updateState
}
}
updateState(obj) {
this.setState(obj);
}
render() {
return (
<ComposedComponent {...this.props} {...this.state} />
)
}
}
And here is an example of a class that would use it (I'm using ES7 for simplicity):
#BaseComponent
class Home extends React.Component {
static displayeName = 'Home';
constructor(props) {
super(props);
// And here I am binding to it
this.updateState = this.props.updateState.bind(this);
}
render() {
return (
<div>Hi</div>
)
}
}

Categories