Как изменить выборку вызова и перерисовку экрана? - PullRequest
0 голосов
/ 06 ноября 2019

У меня есть приложение React Native, которое обменивается данными с PostgresDB, сгенерировало API-интерфейс REST ExpressJS.

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

Моя проблема заключается в том, что URL-адрес выборки должен обновляться при изменении состояния даты, а затем возвращатьданные за данный день. В настоящее время экран не перерисовывается, а дата меняется. Есть ли конкретный способ, как сказать моему запросу на выборку, что он должен быть обработан?

Например: `http://myip/api/hours/daydata/${realDate}/${userid}` - это мой fetchurl, а realDate - это this.state.date, а идентификатор пользователя - это сохраненный идентификатор пользователя AsyncStorage.

`http://myip/api/hours/daydata/2019-11-06/138` этот URL возвращает мне данные, которые мне нужны для данного дня и для пользователя.

При нажатии кнопки мое состояние даты изменяется, например, на 2019-11-07. `http://myip/api/hours/daydata/2019-11-07/138` это будет новый URL-адрес, который должен быть получен следующим, и я ожидаю перерисовать экран, чтобы увидеть изменения. Но он не рендерится!

Здесь у вас есть код:

 async fetchData() {
    let realDate = this.state.date;
    await getData("userid")      // asyncStorage gets userid correctly
      .then(data => data)
      .then(value => this.setState({ userid: value }))
      .catch(err => console.log("AsyncS_Error: " + err));

    const userid = this.state.userid;
    console.log("cpmDM id_ " + userid);


    await fetch(
      `http://myip/api/hours/daydata/${realDate}/${userid}`
      )
      .then(console.log("realD8_: " + realDate))
      .then(res => res.json())
      // .then(res => console.log(res))
      .then(res => {
        console.log(res[0].remark);
        return this.setState({ 
          remark: res[0].remark
        });
      }) 
      .catch(err => console.log(err));
  }


componentDidMount() {
    this.fetchData();
  }

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

Идеи:

Есть ли способ записать текущий fetchurl? Нужно ли мне что-то вроде componentWillUpdate?

РЕДАКТИРОВАТЬ: Это способ обновления моего состояния:

dateForwardHandler = () => {
    console.log("Current Date:", this.state.date);

    const newDate = Moment(this.state.date).add(1, "d").format("YYYY-MM-DD");
    this.setState({ date: newDate.toString() });

    console.log("Current Date:", this.state.date);
  };

РЕДАКТИРОВАТЬ 2.0:

вызывая fetchData () внутриdateBackHandler и dateForwardHandler на самом деле показывают мне различные замечания, где они мне нужны, но почему-то у них 1 выходной. Если я возвращаюсь в дату для ex к 25.10, я получаю замечание от 26.10, и когда я затем иду к 24.10, я получаю замечание от 25.10

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

РЕДАКТИРУЕТСЯ СЛОВАНО: Спасибо за всю помощь, которую вы, ребята, оказали мне.

Я хочу рассказать вам, как в настоящее время ведет себя приложение.

dateForwardHandler = () => {
    console.log("Current Date:", this.state.date);

    const newDate = Moment(this.state.date).add(1, "d").format("YYYY-MM-DD");
    this.setState({ date: newDate.toString() });

    console.log("Current Date:", this.state.date);

    this.fetchData();   // THIS CALL IS NEW 
  };

Вызвав this.fetchData ();после изменения состояния и нажатия кнопки я получаю несколько других замечаний, но у меня проблема в том, что у меня всегда один выходной. Таким образом, интерфейс и вызов fetch не обновляются одновременно. Но я думаю, что правильно сначала установить state.date на новую дату, а затем вызвать fetchData ...

Спасибо за всю помощь;)

Ответы [ 3 ]

0 голосов
/ 06 ноября 2019

Зачем вам нужна текущая дата в вашем штате и обновлять ее каждый раз, когда это необходимо? Вы не можете просто сделать:

let currentDate = Moment().add(1, "d").format("YYYY-MM-DD").toString()

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

0 голосов
/ 06 ноября 2019

Прежде всего, я бы не помещал два ожидания в одну асинхронную функцию. Возможно, ваш userId не будет вовремя извлечен для вашего метода извлечения.

Что касается повторного рендеринга, попробуйте сначала вернуть результат fetchData (res.json), а затем setState вне асинхронной функции.

РЕДАКТИРОВАТЬ:

Как вы упоминали, что вы хотите сделать по нажатию кнопки, это может выглядеть примерно так:

fetchData = (url, method) => {
    let error;
    return fetch(url, {
      method: method,
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
    }).then((response) => {
      if (response.ok) {
        return response.json().then(response => ({ response })).catch((error) => { console.log("JSON cannot be parsed") });
      } 
      error = JSON.stringify(response);
      return ({ error });
    }).catch((error) => {
      console.log("Promise rejected");
    });
  }



onButtonPress = async () => {    
    const userid = this.state.userid;
    const realDate = this.state.realDate;
    const { response, error } = await this.fetchData('http://myip/api/hours/daydata/${realDate}/${userid}', 'GET'); 
    if (response) {
        console.log(response);
        this.setState({ 
          remark: response[0].remark
        });
    } else {
        console.error("Error: " + error);
    }
}
0 голосов
/ 06 ноября 2019

Вам не нужно возвращать this.setState, поэтому вместо

return this.setState({ 
 remark: res[0].remark
});

используйте

this.setState({ 
 remark: res[0].remark
});
...