Ce problème m'a causé un mal de tête. Le mot clé this lorsque vous définissez un état n'est pas accessible à l'intérieur du ajax call.

Je pense que je comprends mal le fonctionnement des composants.

Comment dois-je utiliser le mot clé this dans cette situation spécifique, comme indiqué ci-dessous? et en général si this n'est pas accessible.

class PollsList extends Component {
    constructor() {
        super();

        this.state = {
            polls: []
        }
    }
    componentDidMount() {
        $.ajax({
            url: "/mypolls",
            type: 'get',
            dataType: 'json',
            contentType: 'application/json',
            success: function (polls_list) {
                console.log(polls_list);

                for (let i = 0; i < polls_list.length; i++) {
                    let data = polls_list[i].poll[0];
                     this.setState(()=>{polls:data});
                }
            },
            error: function (err, status, xhr) {
                console.log(err);
            }
        });
    }
    render() {
        return (
            <Fragment>
                <div class='container'>
                    <ul id='polls_list'>{this.state.polls}</ul>
                </div>
            </Fragment>
        )
    }
}

MODIFIER: PROBLÈME RÉSOLU!

Merci pour tout le monde a contribué.

class PollsList extends Component {
    constructor() {
        super();
        this.state = {
            polls: []
        }

        this.fetchPolls = this.fetchPolls.bind(this);
    }
    componentDidMount() {
        $.ajax({
            url: "/mypolls",
            type: 'get',
            dataType: 'json',
            contentType: 'application/json',
            success: (polls_list)=>this.fetchPolls(polls_list), // this must look like that.
            error: (err, status, xhr) =>{
                console.log(err);
            }
        });
    }

    fetchPolls(polls_list){
        for (let i = 0; i < polls_list.length; i++) {
            let data = polls_list[i].poll[0];
            this.setState({polls:data});
        }
    }
    render() {
        console.log(this.state.polls);
        return (
            <Fragment>
                <div className='container'>
                    <ul id='polls_list'>{this.state.polls.option1} {this.state.polls.option2}</ul>
                </div>
            </Fragment>
        )
    }
}
0
Sharl Sherif 23 mai 2018 à 07:44

4 réponses

Meilleure réponse

Dans ce scénario, votre this est dans le contexte de cette fonction au lieu de la classe de composants:

function (polls_list) {
  for (let i = 0; i < polls_list.length; i++) {
    let data = polls_list[i].poll[0];
    this.setState(()=>{polls:data});
  }
}

Une meilleure pratique pour faire face à ce genre de situation est de lier this qui toujours dans le contexte du composant dans le constructeur du composant:

class PollsList extends Component {
  constructor() {
    super();

    this.state = {
        polls: []
    }

    this.successHandler = this.successHandler.bind(this);
  }

  componentDidMount() {
    $.ajax({
        url: "/mypolls",
        type: 'get',
        dataType: 'json',
        contentType: 'application/json',
        success: this.successHandler(polls_list),
        error: function (err, status, xhr) {
            console.log(err);
        }
    });
  }

  successHandler(polls_list) {
    for (let i = 0; i < polls_list.length; i++) {
      let data = polls_list[i].poll[0];
      this.setState(()=>{polls:data});
    }
  }

  render() {
    ...     
  }
}
2
Carr 24 juil. 2019 à 04:22

Liez this au gestionnaire de réussite dans le constructeur. Cela devrait résoudre la portée de l'objet this

constructor (args) {
   super(...args);
   /* some state variables */

   this.successHandler = this.successHandler.bind(this);
}

function successHandler(polls_list) {
  for (let i = 0; i < polls_list.length; i++) {
     let data = polls_list[i].poll[0];
        this.setState(()=>{polls:data});
   }
}

function (err, status, xhr) {
   console.log(err);
}

componentDidMount() {
  $.ajax({
    url: "/mypolls",
    type: 'get',
    dataType: 'json',
    contentType: 'application/json',
    success: successHandler,
    error: errorHandler
  });
}
2
A.V.D. Kishore 23 mai 2018 à 05:07

Je pense que la façon la plus propre de résoudre ce problème consiste à utiliser les fonctions de flèche grasse (qui se lient automatiquement au composant). Donc, votre composant ressemblerait à ceci:

class PollsList extends Component {
    // You can also set default state if your webpack can handle it
    state = {
        polls: []
    }
    componentDidMount() {
        $.ajax({
            url: "/mypolls",
            type: 'get',
            success: this.successHandler,
        });
    }
    // Fat arrow functions auto binds to this to the Class
    successHandler = response => { 
        // handle the response
    } 
    render() {
        return (
            <Fragment>...</Fragment>
        )
    }
}
0
Juan Solano 1 mars 2019 à 18:04

Une solution rapide serait de simplement

const var that = this

À l'intérieur de componentDidMount, puis utilisez that.setState

Cela aurait pour effet d'enregistrer le contexte de ceci dans la variable "that" pour une utilisation ultérieure. ou mieux faire ça

success: function (polls_list) {
                console.log(polls_list);

                for (let i = 0; i < polls_list.length; i++) {
                    let data = polls_list[i].poll[0];
                     this.setState(()=>{polls:data});
                }
            }.bind(this),

Cela liera le contexte à la fonction de réussite

1
supra28 23 mai 2018 à 04:54