0

I am trying to wrap my head around ReactJS and I am stumped with an issue where I want to be able to update the value of a local variable and return the updated value.

I've read about state and I've used that when working with React Components, however, this class is just defined as const and it doesn't extend React.Component.

Is there a different way I should be defining setting the variable?

Here is a simplified version of my code:

import React from 'react';

const WelcomeForm = ({welcome}) => {

    var welcomeMsg = 'Test';

    DynamicContentApi.loadDynamicContent('welcome_test').then((response) => {
       // response.text has content
       welcomeMsg = response.text;
    }).catch(() => {
        welcomeMsg = '';
    });

    return (
                <p>{welcomeMsg}</p> // Returns 'Test'
    );
};

export default WelcomeForm;

5
  • DynamicContentApi.loadDynamicContent( ) - what is that? Commented Feb 16, 2018 at 20:00
  • This is not a simplified version of the class. You are trying to use a stateless component as a stateful component. you can update as many variables as you want, but React won't re-render in a stateless component :) Commented Feb 16, 2018 at 20:01
  • Ordinary variable does not rerender the component when updated. If you want to write this logic here then i would recomment you to use state by extending React.component. Commented Feb 16, 2018 at 20:01
  • Other way would be to move DynamicContentApi logic above in the hierarchy and pass the result as a prop to this component. Commented Feb 16, 2018 at 20:02
  • Tiago's answer is the correct approach to fix your problem. The reason your code doesn't work is because loadDynamicContent executes asynchronously, so by the time it completes, your component has already rendered with 'Test'. And since welcomeMsg is just a local variable, it won't trigger a re-render when it changes (as it would if it were a prop or kept in state). Commented Feb 16, 2018 at 22:21

2 Answers 2

2

The easiest option here is to change your stateless component to a stateful component.

Stateless components are just JavaScript functions. They take in an optional input, called prop.

Stateful components offer more features, and with more features comes more baggage. The primary reason to choose class components (stateful) over functional components (stateless) is that they can have state, that is what you want to update to re-render.

Here is what you can do:

class WelcomeForm extends React.Component {
  state = {
    welcomeMsg: ''
  }
  fetchFromApi() {
    DynamicContentApi.loadDynamicContent("welcome_test")
    .then(response => {
      this.setState({welcomeMsg: response.text});
    })
    .catch((e) => console.log(e));
  }
  componentDidMount() {
    fetchFromApi();
  }
  render() {
    return (
      <p>{welcomeMsg}</p>
    );
  }
};

If you want, for any reason, to keep your component stateless, you will have to put the loadDynamicContent() function on the Parent and pass the text to WelcomeForm as a prop. For example:

// Your WelcomeForm Component
const WelcomeForm = ({welcomeMsg}) => (
  <p>{welcomeMsg}</p>
);

// Whatever it's Parent Component is
class Parent extends React.Component {
  state = {
    welcomeMsg: ''
  }
  fetchFromApi() {
    DynamicContentApi.loadDynamicContent("welcome_test")
    .then(response => {
      // response.text has content
      this.setState({welcomeMsg: response.text});
    })
    .catch((e) => console.log(e));
  }
  componentDidMount() {
    fetchFromApi();
  }
  render() {
    <WelcomeForm welcomeMsg={this.state.welcomeMsg} />
  }
}
Sign up to request clarification or add additional context in comments.

Comments

0

As suggested in the comments, you can pass the DynamicContentApi logic to outside:

import ReactDOM from 'react-dom'

DynamicContentApi.loadDynamicContent('welcome_test').then((response) => {
  ReactDOM.render(<WelcomeForm data={response.text} />, document.getElementById('where you wanna render this'));
}).catch(() => {
  console.log('error while fetching...');
});

And where you have your component:

import React from 'react';

export default class WelcomeForm extends React.Component {
  render() {
    return (
      <p>{this.props.data}</p>
    );
  }
}

9 Comments

ReactDOM is not defined :P
Why do you need to assign this.props.data to yourMessage when you can use <p>{this.props.data}</p> or just name the prop as message and then use <p>{this.props.message}</p>
I'm trying to help too :)
@ArberSylejmani I know that, but that is not so relevant to the case.
No, but when you answer, take your time and write a proper answer.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.