2017-01-05 2 views
0

Я сделал компонент, который загружает данные через xhr на пользователя, выберите значение <, выберите >.Состояние компонента не обновляется с помощью обработчика select и onChange

class SomeComponent extends Component { 
    state = { 
     data: [], 
     currentCategory: 'all' 
    } 
    switchCategory = (ev) => { 
     console.log('Selected category is ' + ev.target.value); 

     this.setState({ 
      currentCategory: ev.target.value 
     }); 

     this.loadData(); 
    } 
    loadData = async() => { 
     let { currentCategory } = this.state; 

     // Always print previous value!!! 
     console.log(currentCategory); 

     // Get data via XHR... 
    } 
    render() { 
     return (
      <div> 
       <select value={currentCategory} onChange={this.switchCategory}> 
        <option value="all">All</option> 
        {categories.map(category => 
        <option key={category._id} value={category.category}>{category.display}</option>  
        )} 
       </select> 

       <table> 
        // ... prints data with this.state.data 
       </table> 
      </div> 
     ); 
    } 
} 

Выше кода вкратце. Код довольно прост, я просто синхронизирую значение элемента select с this.state.currentCategory и обнаруживаю, что он переключается с помощью метода switchCategory этого класса.

Но основная проблема заключается в том, что когда я обращаюсь к состоянию компонента, он всегда содержит предыдущее значение, а не настоящее. Вы можете видеть, что я обновляю текущую категорию по значению выбранных изменений.

switchCategory = (ev) => { 
     console.log('Selected category is ' + ev.target.value); 

     this.setState({ 
      currentCategory: ev.target.value 
     }); 

     this.loadData(); 
    } 

Таким образом, в этой ситуации, this.state.currentCategory не должен есть «все», как-то иначе «Apple», но все же он содержит «все», а не «Apple»!

loadData = async() => { 
     let { currentCategory } = this.state; 

     // Always print previous value!!! I expected "Apple", but it has "all" 
     console.log(currentCategory); 

     // Get data via XHR... 
    } 

Так что в конечном итоге XHR встречается с предыдущим значением, и это дает мне неправильные данные, которых я не ожидал. После этого, выбирая другое значение select (назовем его Banana), у него есть Apple, а не банан!

Как я знаю, setState является «синхронизирующим» заданием, поэтому вызов this.switchCategory произойдет после обновления состояний, поэтому он должен иметь текущее значение, а не предыдущее.

Но когда я печатаю состояние компонента в консоли, это не так.

Итак, что мне не хватает? Почему я всегда получаю старые данные, не представляю? Если я сделаю неправильный подход, то какие альтернативы я могу сделать?

Любой совет очень понравится. Благодаря!

+1

ли следы от выбранной категории печатает правильный выбранной категории? Вы пытались удалить асинхронный режим? – Kinnza

+1

Вы связали onChange? добавьте конструктор в верхней части вашего класса и в конструкторе: this.onChange = this.onChange.bind (this) ' – Celebrian

+0

Спасибо, что помогли мне, ребята! – modernator

ответ

1

Проблема заключается в том, что setState is async (в определенных ситуациях это может быть синхронизация). Вот почему вы получаете предыдущее значение.

Существует два возможных решения.

// 
// 1. use value directly. 
// 
switchCategory = (ev) => { 
    this.setState({ currentCategory: ev.target.value }); 
    this.loadData(ev.target.value); 
} 

loadData = async (currentCategory) => { 
    console.log(currentCategory); 

    // Get data via XHR... 
} 

// 
// 2. use completition callback on `setState`. 
// 
switchCategory = (ev) => { 
    this.setState({ currentCategory: ev.target.value },() => { 
     this.loadData(ev.target.value); 
    }); 
} 

loadData = async() => { 
    const { currentCategory } = this.state; 
    console.log(currentCategory); 

    // Get data via XHR... 
} 

Статья о в синхронном setState Реагировать [link]

+0

Можете ли вы объяснить «определенные ситуации» в async setState? Я просто хочу знать наверняка. – modernator

+0

О, я только что нашел объяснение setState в документации! Это было асинхронно, и я этого не знал! Спасибо, Андрейко! – modernator

+1

@modernator Я обновил свой ответ со ссылкой на статью – Andreyco

Смежные вопросы