1
votes

I'm beginner on react and i've written the code below:

class Note extends React.Component {
   constructor(props) {
       super(props);
       this.state = {editing: false};

        this.edit = this.edit.bind(this);
        this.save = this.save.bind(this);

   }

   edit() {
       // alert('edit');
       this.setState({editing: !this.state.editing});
   }

   save() {
       this.props.onChange(this.refs.newVal.value, this.props.id);
       this.setState({editing: !this.state.editing});
       // console.log('save is over');
   }

   renderForm() {
       return (
           <div className="note">
               <textarea ref="newVal"></textarea>
               <button onClick={this.save}>SAVE</button>
           </div>
       );
   }

   renderDisplay() {
       return (
           <div className="note">
               <p>{this.props.children}</p>
               <span>
                         <button onClick={this.edit}>EDIT</button>
                        <button onClick={this.remove}>X</button>
               </span>
           </div>
       );
   }

   render() {
       console.log(this.state.editing);
       return (this.state.editing) ? this.renderForm()
           : this.renderDisplay()

   }
}

class Board extends React.Component {

   constructor(props){
       super(props);

       this.state = {
           notes: []
       };

       this.update = this.update.bind(this);
       this.eachNote = this.eachNote.bind(this);
       this.add = this.add.bind(this);
   }

   nextId() {
       this.uniqeId = this.uniqeId || 0;
       return this.uniqeId++;
   }

   add(text) {
       let notes = [
           ...this.state.notes,
           {
               id: this.nextId(),
               note: text
           }
       ];

       this.setState({notes});
   }

   update(newText, id) {
       let notes = this.state.notes.map(
           note => (note.id !== id) ?
               note :
               {
                   id: id,
                   note: newText
               }
       );
       this.setState({notes})
   }

    eachNote(note) {
       return (<Note key={note.id}
                     id={note.id}
                     onChange={this.update}>

           {note.note}
       </Note>)
   }

   render() {
       return (<div className='board'>
           {this.state.notes.map(this.eachNote)}
           <button onClick={() => this.add()}>+</button>
       </div>)
   } 
}

ReactDOM.render(<Board />,
   document.getElementById('root'));

In render(), onClick event has a function, that is, if used in this way: {this.add} the following error is created:

Uncaught Error: Objects are not valid as a React child (found: object with keys {dispatchConfig, _targetInst, nativeEvent, type, target, currentTarget, eventPhase, bubbles, cancelable, timeStamp, defaultPrevented, isTrusted, view, detail, ...})

Why? while in the eachNote() method this command is used:

onChange={this.update}

And there was no error.

Someone can tell me the reason? thanks.

3

3 Answers

2
votes

The problem is that in the add function you are taking an argument text and setting it in the state so when you call onClick={() => this.add()}, you are not passing any argument to add function and hence in its definition text is undefned and hence state note is set as undefined.

However if you directly call it like onClick={this.add} , the add function receives the event object as a parameter and hence it sets state note to be an event object which you are using to render

1
votes

onClick={this.add} will pass the click event to this.add.

So what you need to do is either:

onClick={e => this.add('some text')} or similar.

If you want to onClick={this.add} you have to ensure that your add method is: add(event) { ... } instead.

0
votes

The <Note /> component does not contain a render() method to return anything. Add a render() method and return something.

class Note extends React.Component {
   constructor(props) {
       super(props);
       this.state = {editing: false};

        this.edit = this.edit.bind(this);

   }

   edit() {
       // alert('edit');
       this.setState({editing: !this.state.editing});
   }
   
   render() {
     return (
       <div>Render something</div>
     )
   }
}

class Board extends React.Component {

   constructor(props){
       super(props);

       this.state = {
           notes: []
       };

       this.update = this.update.bind(this);
       this.eachNote = this.eachNote.bind(this);
       this.add = this.add.bind(this);
   }

   nextId() {
       this.uniqeId = this.uniqeId || 0;
       return this.uniqeId++;
   }

   add(text) {
       let notes = [
           ...this.state.notes,
           {
               id: this.nextId(),
               note: text
           }
       ];

       this.setState({notes});
   }

   update(newText, id) {
       let notes = this.state.notes.map(
           note => (note.id !== id) ?
               note :
               {
                   id: id,
                   note: newText
               }
       );
       this.setState({notes})
   }

    eachNote(note) {
       return (<Note key={note.id}
                     id={note.id}
                     onChange={this.update}>

           {note.note}
       </Note>)
   }

   render() {
       return (<div className='board'>
           {this.state.notes.map(this.eachNote)}
           <button onClick={() => this.add()}>+</button>
       </div>)
   } 
}

ReactDOM.render(<Board />,
   document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script>

<div id="root"></div>