Первый вызов функции для изменения состояния не обновляет поля - PullRequest
0 голосов
/ 12 апреля 2019

Так что в основном я интегрирую GraphQL с веб-приложением React, чтобы провести некоторое тестирование и узнать немного больше о стеке (простите, если я новичок).

Просто, чтобы возобновить его, у меня в основном есть приложение для библиотеки книг, где у нас есть список книг и список авторов, и автор может написать много книг, и книга связана с автором.

У меня есть 1 компонент базового класса, где живет моя логика (на данный момент это корневой файл app.js), вы можете увидеть ниже код:

APP.JS

import React, { Component } from "react";
import ApolloClient from "apollo-boost";
import { ApolloProvider } from "react-apollo";

import BooksList from "./components/Books/Books";
import AddBook from "./components/AddBook/AddBook";

const client = new ApolloClient({
  uri: "http://localhost:4000/graphql"
});

class App extends Component {
  state = {
    name: "",
    genre: "",
    authorId: ""
  };

  addAuthorHandler = (e, name) => {
    console.log(e.target.value);
    this.setState({
      [name]: e.target.value
    });

    console.log(this.state);
  };

  render() {
    return (
      <ApolloProvider client={client}>
        <div className="bookList">
          <BooksList />
        </div>
        <AddBook addAuthor={this.addAuthorHandler.bind(this)} />
      </ApolloProvider>
    );
  }
}

export default App;

проблема связана с функцией addAuthorHandler, при первом вызове она получает значения, но состояние не обновляется должным образом.

Поскольку компонент booklist для этого случая не важен (так как он отображает только книги, ничего больше), компонент AddBook ссылается на функцию addAuthorHandler в опоре, код ниже:

import React from "react";
import { Query } from "react-apollo";
import { getAuthorsQuery } from "../../graphql/queries/queries";
import Classes from "./AddBook.module.css";

const getAuthors = ({ data: { authors }, loading }) => {
  let render = <option disabled>Loading authors...</option>;

  if (!loading) {
    render = authors.map(author => {
      return (
        <option value={author.id} key={author.id}>
          {author.name}
        </option>
      );
    });
  }

  return render;
};

const addBook = props => {
  return (
    <div className={Classes.addBook}>
      <form className={Classes.form}>
        <div className={Classes.formBlock}>
          <span>Book Name</span>
          <div>
            <input
              className={Classes.input}
              type="text"
              onChange={e => props.addAuthor(e, "name")}
            />
          </div>
        </div>

        <div className={Classes.formBlock}>
          <span>Genre</span>
          <div>
            <input
              onChange={e => props.addAuthor(e, "genre")}
              className={Classes.input}
              type="text"
            />
          </div>
        </div>

        <div className={Classes.formBlock}>
          <span>Author</span>
          <select
            className={Classes.select}
            onChange={e => props.addAuthor(e, "authorId")}>
            <Query query={getAuthorsQuery}>
              {data => {
                return getAuthors(data);
              }}
            </Query>
          </select>
        </div>
      </form>
    </div>
  );
};

export default addBook;

Выше у меня есть метод onChange, который ссылается на реквизит addAuthor и передает событие и имя свойства, которое будет обновлено внутри состояния.

Первое изменение никогда не происходит.

В тот момент, когда я загружаю приложение для каждого ввода, когда пишу 'a', состояние для этого свойства пустое, даже если значение передается в обработчик функции, если я пишу больше клавиш, например 'ab', состояние обновляется с «а».

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

Любая помощь с этими парнями, и возможное объяснение проблемы?

Большое спасибо.

1 Ответ

1 голос
/ 12 апреля 2019

setState работает асинхронно. Это означает, что вызов this.setState не приведет к немедленному изменению переменной this.state. Вы должны реализовать обратный вызов для этого. что-то вроде -

addAuthorHandler = (e, name) => {
    console.log(e.target.value);
    this.setState({
      [name]: e.target.value
    }, function () {
      console.log(this.state)
    });    
  };
...