1

I have a textarea that I want to stringify to JSON on form submission. I will even settle for just having the function set the textarea value.

import React from 'react';

export default class ClinicalMain extends React.Component {
  constructor(props) {
    super(props);
  }

  state = {selectedOption: ''}

  // my function to update the textarea
  reactStringify() {
    let obj = {
      name: "bob",
      age: 4
    }

    console.log('in stringify');
    let value = JSON.stringify(obj);
  }

  componentDidMount() { }

  render() {
    return (
      <React.Fragment>
        <form>
          <button type="button" 
                  onClick={this.reactStringify} 
                  id="reactid"
          >React stringify</button>
          <textarea value={this.value} 
                    defaultValue="" 
                    rows="10" cols="80"
          ></textarea>
          <br />
        </form>
      </React.Fragment>
    )
  }
}

let value does not update. Do I need to use setState? this?

ggorlen
  • 44,755
  • 7
  • 76
  • 106
  • I am just wanting to set any value in the function to change/update the textarea box value.... Seems like it should be "easy" but having trouble –  Aug 20 '19 at 19:08
  • Welcome to SO! Sorry, but I'm not really clear on what you're trying to accomplish. Can you clarify what the user is expected to enter into the textarea, and what should happen when the button is clicked? Without knowing exactly what is supposed to happen, I can say that you'll want to try using `this.setState()` to set state. – ggorlen Aug 20 '19 at 19:12
  • I want to have function called (which it does ) and then just have it setting the value to of the textarea to anything ( i will want to set to json stringify of an entire form) for now I just want to get it to update –  Aug 20 '19 at 19:15
  • @ggorlen see above comment. So if I use this.setState(put what here?) –  Aug 20 '19 at 19:16
  • It's more than that. I would [read the docs](https://reactjs.org/docs/state-and-lifecycle.html)--this is pretty fundamental to React and the way this code is set up indicates that this page hasn't been looked at yet. You'll need a controlled component using `this.state.value` and `this.setState({value: "foobar"})`. – ggorlen Aug 20 '19 at 19:18
  • Ok so i updated it, but i get this error `Uncaught TypeError: Cannot read property 'setState' of undefined` –  Aug 20 '19 at 19:41
  • @ggorlen Ok - I put in a jsfiddle https://jsfiddle.net/xg3pc5L9/ –  Aug 20 '19 at 20:15
  • OK, seems like you need to bind `this`: https://jsfiddle.net/sr4kLzch/2/ – ggorlen Aug 20 '19 at 20:25
  • Thanks - I don't understand, I need to study this. –  Aug 20 '19 at 20:34
  • No problem. Like I said, spend a few hours walking through a React tutorial and all of this will make sense. Should I add my fiddle as an answer with some explanation? If you add a bit about the desired behavior, I can add that too (it looks like you want to parse JSON or do some kind of conversion...?) – ggorlen Aug 20 '19 at 20:48
  • @ggorlen yes please add answer and explanation and fiddle - that way it helps me, others and gives you point credit u deserve thx again –  Aug 20 '19 at 23:03

1 Answers1

0

There are a number of issues in the code indicating a lack of familiarity with the excellent React tutorial. As with any library, it's necessary to spend time reading the manual before diving in.

  1. State should not be modified directly. Use this.setState() to replace state. this.setState() doesn't work instantly; it simply informs the React library that the state needs updating and React handles the update on its own when it sees fit.

    Beyond this, let value = ... is a purely local variable, not a class variable, so this.value would be undefined in render no matter what; in other words, your code doesn't attempt to modify or access state in any way.

  2. Class functions that attempt to access this need to be bound. For example, onClick={this.reactStringify} passes a reference to the this.reactStringify function, but this will be undefined inside of this.reactStringify unless an arrow function is used (which implicitly binds this), or this is explicitly bound:

     this.handleChange = this.handleChange.bind(this);
    

    Explicit is considered to be better practice for class components than the arrow function approach because it only requires one call to bind when the component is constructed.

  3. React typically uses something called controlled components to listen to changes on a text field. This means that the element's value tracks component state and acts as the single source of truth.

While I'm not exactly sure what you're ultimately looking to accomplish, here's a working example to get you moving again which demonstrates the above concepts.

class ClinicalMain extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: "", output: ""};
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }
  
  handleChange({target: {value}}) {
    this.setState(() => ({value}));
  }

  handleSubmit(e) {
    e.preventDefault();
    this.setState(state => ({
      output: `you wrote: "${state.value}"`
    }));
  }

  render() {
    return (
      <React.Fragment>
        <form onSubmit={this.handleSubmit}>
          <textarea
            value={this.state.value}
            onChange={this.handleChange}
          ></textarea>
          <div>
            <input type="submit" value="Show output" />
          </div>
        </form>
        <div>{this.state.output}</div>
      </React.Fragment>
    );
  }
}

ReactDOM.createRoot(document.querySelector("#app"))
  .render(<ClinicalMain name="World" />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="app"></div>

Here are relevant sections of the documentation which provide more detail:

ggorlen
  • 44,755
  • 7
  • 76
  • 106
  • thx, i need to ask another question ... as I am wanting to now take the entire form and stringify it and put it into the textarea box . I was looking at `new FormData(this.form);` but not figured that out yet . –  Aug 21 '19 at 01:02
  • That's basically what I was prompting you for in the comments section. I'm not really clear on what you're doing here. What constitutes the entire form? What do you mean by stringifying? The textarea is already a string. You can post a vanilla HTML structure that you're using and explain the desired result. But at this point, I'd recommend opening up a new question, because it's beginning to turn into a moving goalpost. – ggorlen Aug 21 '19 at 01:24
  • Ok, here it is https://stackoverflow.com/questions/57597464/json-stringify-entire-form-data-with-reactjs –  Aug 21 '19 at 18:35