0

I did 2 tutorials on using REACT. "to-do-app" is a django/react project while "robofriends" is a purely react project. "to-do-app" uses .bind(this) for its functions while "robofriends" does not use this method. While i understand why the .bind method is needed, i do not understand why "robofriends" was able to work without binding its functions.

to-do app (apps.js)

import React from 'react';
import './App.css';

class App extends React.Component{
  constructor(){
    super();
    this.state={
      todoList:[],
      activeItem:{
        id:null,
        title:"",
        completed:false
      },
      editing:false,
    }
    this.fetchTasks=this.fetchTasks.bind(this)
    this.handleChange=this.handleChange.bind(this)
    this.handleSubmit=this.handleSubmit.bind(this)
  }

  componentWillMount(){
    this.fetchTasks()
  }

  fetchTasks(){
    console.log('fetching')
    fetch('http://127.0.0.1:8000/api/task-list/')
    .then(response=>response.json())
    .then(data=>
      this.setState({todoList:data})
      )
  }

  handleChange(e){
    const name=e.target.name;
    const value=e.target.value;
    console.log('Name', name)
    console.log('Value', value)
    this.setState({
      activeItem:{
        ...this.state.activeItem,
        title:value
      }
    })
  }

  handleSubmit(e){
    e.preventDefault()
    console.log('ITEM', this.state.activeItem)

    var url='http://127.0.0.1:8000/api/task-create/'
    fetch(url, {
      method:'POST',
      headers:{
        'Content-type':'application/json',
      },
      body:JSON.stringify(this.state.activeItem)
    }).then((response) =>{
      this.fetchTasks()
      this.setState({
       activeItem:{
        id:null,
        title:"",
        completed:false
      }
      })
    }).catch(function(error){
      console.log('ERROR', error)
    })

  }

  render(){
    const tasks=this.state.todoList
    return(
      <div className="container">
        <div id="task-container">

          <div id="form-wrapper">
            <form onSubmit={this.handleSubmit} id="form">
              <div className="flex-wrapper">
                <div style={{flex:6}}>
                  <input onChange={this.handleChange} className="form-control" id="title" type="text" name="title" placeholder="Add task" />
                </div>
                <div style={{flex:1}}>
                  <input id="submit" className="btn btn-warning" type="submit" name="Add" />
                </div>
              </div>
            </form>
          </div>

          <div id="list-wrapper">
            {tasks.map((task, index)=>{
              return(
                <div key={index} className="task-wrapper flex-wrapper">
                  <div style={{flex:7}}>
                    <span>{task.title}</span>
                  </div>
                  <div style={{flex:1}}>
                    <button className="btn btn-sm btn-outline-info">Edit</button>
                  </div>
                  <div style={{flex:1}}>
                    <button className="btn btn-sm btn-outline-dark delete">-</button>
                  </div>
                </div>
                )
            })}
          </div>

        </div>
      </div>
    )
  }
}

export default App;

robofriends(apps.js)

import React, {Component} from 'react';
import CardList from '../components/Cardlist';
// import {robots} from './robots';
import SearchBox from '../components/SearchBox';
import './App.css';
import Scroll from '../components/Scroll';
import ErrorBoundary from '../components/ErrorBoundary';


class App extends Component {
    constructor(){
        super()
        this.state={
            robots:[],
            searchfield:''
        } //a state is what changes in an app
    }

    componentDidMount(){
        fetch('https://jsonplaceholder.typicode.com/users')
        .then(response=> response.json())
        .then(users => this.setState({robots:users}))
    }



// remember to use => for functions you create yourself. 
    onSearchChange=(event) => {
        this.setState({searchfield:event.target.value})
    }

    render(){
        const {robots, searchfield}=this.state;
        const filteredRobots=robots.filter(robot=>{
            return robot.name.toLowerCase().includes(searchfield.toLowerCase());
        })
        if (!robots.length){
            return <h1>Loading</h1>
        }else{
    return(
        <div className='tc'>
            <h1 className='f1'>Robofriends</h1>
            <SearchBox searchChange={this.onSearchChange}/>
            <Scroll>
            <ErrorBoundary>
            <CardList robots={filteredRobots}/>
            </ErrorBoundary>
            </Scroll>
        </div>
        );
    }
}
}   

 export default App;

robofriends 'searchbox.js'

import React from 'react';

const SearchBox=({searchChange})=>{
    return (
        <div className='pa2'>
            <input 
                className='pa3 ba b--green bg-lightest-blue'
                type='search' 
                placeholder='search robots' 
                onChange={searchChange}
            />
        </div>
        );
}

export default SearchBox;
ryantan
  • 79
  • 2
  • 7

1 Answers1

1
fetchTasks(){ 

if you define a function like this, then you need to .bind(this)

as this will lose the context of this of class, to maintain it we need to use .bind(this)


But if you use below one then no need to bind, it maintains the context of this, so no need of using .bind(this)

Arrow functions do not bind their own this, instead, they inherit the one from the parent scope, which is called "lexical scoping"

fetchTasks = () => {

For more detail : DO READ

Hope the below snippet will help you get understanding :

const { useState , useEffect } = React;

class App extends React.Component {

  constructor() {
    super();
    this.state = {
      name : "Vivek"
    }
    this.withBound = this.withBound.bind(this);
  }
  
  withoutBound() {
    console.log(this.state.name)
  }

  withBound() {
    console.log(this.state.name)
  }

  withFatArrow = () => {
    console.log(this.state.name)
  }

  render() {
    return (
      <div>
          Check the console on click:
          <br/><br/>
          <button onClick={this.withoutBound}>Without Bind</button>
          <br/><br/>
          <button onClick={this.withBound}>With Bind</button>
          <br/><br/>
          <button onClick={this.withFatArrow}>Fat Arrow</button>
      </div>
    );
  }
  
}

ReactDOM.render(<App />, document.getElementById('react-root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react-root"></div>
Vivek Doshi
  • 56,649
  • 12
  • 110
  • 122