Redux我应该如何处理API调用的更新

时间:2020-09-11 08:47:49

标签: reactjs redux

我有一个触发许多更新的应用程序,我想了解有关正确更新该应用程序的最佳方法的更多信息。

在我的应用中,我有5个插槽可以装满书籍(可以通过拖放进行管理)。应用启动时,将为用户填充已填充的书,并将其存储在状态中。

问题:更新一本书时,例如,如果我切换清单中的2本书的位置,我必须做一些操作,说“这本书现在属于这里,另一本书现在属于这里,切换!”

我觉得我正在做一些乏味的操作,因为如果我只是从API调用中返回全部数据(在更新后获取),然后调用“加载”功能(就像我启动应用程序时一样),不必处理操作更新。

此外,如果我正确加载但未正确更新(例如,如果我错过一本书的位置),它可能会产生错误

我在功能更新中看到的好处是,我只更新了我需要的两本书,而不是一次又一次地重新加载它们。

哪种方法更好?我应该摆脱那些更新功能,而只是完全重新加载数据吗?我认为可能还会有一些图书馆将其缓存,以便仅重新呈现修改后的书

谢谢

1 个答案:

答案 0 :(得分:1)

没有代码很难完全理解问题,但是从服务器获取数据有两个优点。

  1. 您确定ui会显示服务器上的数据
  2. 您的客户端代码不需要包含需要发生的逻辑,服务器具有此逻辑。以某种方式重构逻辑时,它们不会不同步。

因此,我通常选择获取服务器上的数据。

基于用户交互来获取数据的一个问题是,获取是异步的,因此可能发生以下情况:

用户执行操作A,针对A的请求,用户执行操作B,针对B的请求,B请求解析,并且将UI设置为请求B的结果,针对A的请求解析,并将UI设置为A的结果。

因此,用户执行操作的顺序并不能保证解决请求的顺序。

要解决此问题,您可以使用仅在上次请求时才进行解析的助手,在上面的示例中,当一个请求解析出UI时,无需设置任何内容,因为它已被另一个请求替换。

在下面的示例中,您可以键入搜索值,当该值是1个字符长时,将需要2秒钟才能解决,因此当您键入ab时,ab请求将在{{ 1}}请求。但是由于发出请求的函数在a解析时被last帮助程序包装,因此将被拒绝,因为它已被较新的请求a取代。

ab
//constant to reject with when request is replaced with a
//  more recent request
const REPLACED = {
  message: 'replaced by more recent request',
};
//helper to resolve only last requested promise
const last = (fn) => {
  const check = {};
  return (...args) => {
    const current = {};
    check.current = current;
    return Promise.resolve()
      .then(() => fn(...args))
      .then((result) => {
        //see if current request is last request
        if (check.current === current) {
          return result;
        }
        //was not last request so reject
        return Promise.reject(REPLACED);
      });
  };
};

const later = (howLong, value) =>
  new Promise((resolve) =>
    setTimeout(() => resolve(value), howLong)
  );
const request = (value) =>
  later(value.length === 1 ? 2000 : 10, value).then(
    (result) => {
      console.log('request resolved:', result);
      return result;
    }
  );
const lastRequest = last(request);
const App = () => {
  const [search, setSearch] = React.useState('');
  const [result, setResult] = React.useState('');
  React.useEffect(() => {
    //if you use request instead of lastRequest here
    //  you see it will break, UI is updated as requests
    //  resolve without checking if it was the last request
    lastRequest(search)
      .then((result) => setResult(`result:${result}`))
      .catch((err) => {
        console.log(
          'rejected with:',
          err,
          'for search:',
          search
        );
        if (err !== REPLACED) {
          //if the reject reason is not caused because request was
          //  replaced by a newer then reject this promise
          return Promise.reject(err);
        }
      });
  }, [search]);
  return (
    <div>
      <label>
        search
        <input
          type="text"
          value={search}
          onChange={(e) => setSearch(e.target.value)}
        ></input>
      </label>
      <div>{result}</div>
    </div>
  );
};
ReactDOM.render(<App />, document.getElementById('root'));

相关问题