【问题标题】:What's the best practice to call API with react用反应调用 API 的最佳实践是什么
【发布时间】:2018-09-19 22:54:20
【问题描述】:

在调用 API 时,我实际上在 React 中遇到了一个小问题,因为 ComponentWillMount 已被弃用。

我这样做了:

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

    this.state = {
      questionsAnswers: [[{ answers: [{ text: '', id: 0 }], title: '', id: 0 }]],

    },
  };
}
componentDidMount() {
   this.getQuestions();
}

getQuestions = async () => {
   let questionsAnswers = await Subscription.getQuestionsAndAnswers();
   questionsAnswers = questionsAnswers.data;
   this.setState({ questionsAnswers });
};

所以页面在没有questionsAsnwers 的情况下第一次呈现,当我得到questionAnswers 时页面被重新呈现

有没有更好的解决方案来避免重新渲染?

【问题讨论】:

  • 在这种情况下,第一次继续加载符号,一旦加载问题,就会改变状态,这将显示问题..也将获得良好的用户体验..更好地使用 redux,它可以让您更好地处理 api 调用和数据绑定
  • 我建议不要对任何 React 组件方法使用 async 关键字,因为 Promise 是不可取消的。如果在await 期间卸载了组件,您将对卸载的组件调用this.setState。这就是为什么创建像Redux 这样的商店的原因; React 组件最好保持完全同步。如果您确实将异步添加到组件,请在 componentDidMount 中创建订阅并在 componentWillUnmount 中取消订阅,但我建议在 React 组件方法中完全避免使用 async 关键字。
  • 如果你的组件第一次渲染的时候没有数据,那么就按照那个来塑造你的组件。见:stackoverflow.com/questions/49697447/…

标签: javascript reactjs api


【解决方案1】:

根据 react 文档,处理 API 调用的最佳方法是在 componentDidMount 方法 react lifeCycle 中。此时您所能做的就是添加一个微调器以使您的组件更加用户友好。
希望在下一个 React 版本中。 React 将引入一种新的方法来解决这类问题,使用suspense 方法https://medium.com/@baphemot/understanding-react-suspense-1c73b4b0b1e6

【讨论】:

    【解决方案2】:

    使用带有React.Component 的类是componentDidMount

    class MyComponent extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          error: null,
          isLoaded: false,
          items: []
        };
      }
    
      componentDidMount() {
        fetch("https://api.example.com/items")
          .then(res => res.json())
          .then(
            (result) => {
              this.setState({
                isLoaded: true,
                items: result.items
              });
            },
            // Note: it's important to handle errors here
            // instead of a catch() block so that we don't swallow
            // exceptions from actual bugs in components.
            (error) => {
              this.setState({
                isLoaded: true,
                error
              });
            }
          )
      }
    
      render() {
        const { error, isLoaded, items } = this.state;
        if (error) {
          return <div>Error: {error.message}</div>;
        } else if (!isLoaded) {
          return <div>Loading...</div>;
        } else {
          return (
            <ul>
              {items.map(item => (
                <li key={item.id}>
                  {item.name} {item.price}
                </li>
              ))}
            </ul>
          );
        }
      }
    }
    

    如果你使用带有 Hooks 的函数组件,你应该这样做:

    function MyComponent() {
      const [error, setError] = useState(null);
      const [isLoaded, setIsLoaded] = useState(false);
      const [items, setItems] = useState([]);
    
      // Note: the empty deps array [] means
      // this useEffect will run once
      // similar to componentDidMount()
      useEffect(() => {
        fetch("https://api.example.com/items")
          .then(res => res.json())
          .then(
            (result) => {
              setIsLoaded(true);
              setItems(result);
            },
            // Note: it's important to handle errors here
            // instead of a catch() block so that we don't swallow
            // exceptions from actual bugs in components.
            (error) => {
              setIsLoaded(true);
              setError(error);
            }
          )
      }, [])
    
      if (error) {
        return <div>Error: {error.message}</div>;
      } else if (!isLoaded) {
        return <div>Loading...</div>;
      } else {
        return (
          <ul>
            {items.map(item => (
              <li key={item.id}>
                {item.name} {item.price}
              </li>
            ))}
          </ul>
        );
      }
    }
    

    示例响应:

    {
      "items": [
        { "id": 1, "name": "Apples",  "price": "$2" },
        { "id": 2, "name": "Peaches", "price": "$5" }
      ] 
    }
    

    来源:

    https://reactjs.org/docs/faq-ajax.html

    【讨论】:

      【解决方案3】:

      我认为,在这种情况下显示 spinner 是可以的。 您还应该检查 ajax 没有失败。

      【讨论】:

        猜你喜欢
        • 2019-10-21
        • 2013-01-07
        • 2018-02-14
        • 2020-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-13
        • 1970-01-01
        相关资源
        最近更新 更多