【问题标题】:Warning: Can't call setState on a component that is not yet mounted. When calling an API警告:无法在尚未安装的组件上调用 setState。调用 API 时
【发布时间】:2021-09-26 04:03:56
【问题描述】:

当我尝试运行此代码并显示以下错误时。

警告:无法在尚未安装的组件上调用 setState。这是一个无操作,但它可能表明您的应用程序中存在错误。而是直接分配给this.state 或在Api 组件中定义具有所需状态的state = {}; 类属性。

我应该怎么做才能解决这个问题?

class Api extends Component {     

    constructor(props){        

        super(props)
        this.state = {            
            data: [],            
        }

    }
    
    async componentDidMount(){

        this.apiCall()
        
    }
    
    async apiCall() {
        let resp = await fetch(URL)
        let respJson = await resp.json()
        this.setState({data:respJson.data.statistics})
        
    }

}


export default function App(){
    const api = new Api()
    api.componentDidMount()

    return (
        <View>
            <ScrollView style={styles.center}>
            
            <Text>{api.state.data.time}</Text>
            
            </ScrollView>
        </View>
    )
} 

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: '#fff',
        padding: 20,
        alignItems: 'center',
        padding: 15,
    },
    title: {
        padding: 30,
    },
})

使用 Federkun 解决方案后,我得到了这个新错误,我对 JS 很陌生,所以我有点迷路。

我尝试使用异步函数,但一直显示错误。

Failed building JavaScript bundle. SyntaxError: 
C:\Users\yup\Documents\GitHub\LEARN_REACT\App.js: Unexpected reserved word 'await'. (54:19) 52 | 53 | React.useEffect(() => { > 54 | let resp = await fetch(URL) | ^ 55 | let respJson = await resp.json() 56 | setData({data:respJson.data.statistics}) 

【问题讨论】:

    标签: javascript react-native setstate


    【解决方案1】:

    这是对@Federkun 回答的扩展,添加了一些其他有用的道具并修复了一些问题,

    你可以重写你的useApi钩子,

    function useApi() {
      const [data, setData] = React.useState(null);
      const [error, setError] = React.useState(null);
      const [loading, setLoading] = React.useState(false);
    
      React.useEffect(() => {
        const fetchData = async () => {
          setLoading(true);
          try {
            let resp = await fetch('URL'); // your backend url goes here
            let respJson = await resp.json();
            setData(respJson);
          } catch (err) {
            setError(err);
          } finally {
            setLoading(false);
          }
        };
        fetchData();
      }, []);
    
      return { data, error, loading };
    };
    

    并使用,

    export default function App() {
      const { data, loading, error } = useApi();
    
      if (loading)
        return (
          <View style={styles.container}>
            <Text>loading...</Text>
          </View>
        );
      return (
        <View style={styles.container}>
          {data && (
            <Text>{JSON.stringify(data)}</Text>
          )}
          {error && (
            <Text>{JSON.stringify(error)}</Text>
          )}
        </View>
      );
    }
    

    如果你仍然感到困惑,你可以看到它在行动at this live snack

    【讨论】:

      【解决方案2】:

      Api 并不是真正的反应Component。没有渲染功能。而且您需要将其用作 jsx 的一部分,而不是那样。

      但是,有一个有用的原语可以保持状态:钩子。

      function useApi() {
        const [data, setData] = React.useState()
      
        React.useEffect(() => {
          async function load() {
            let resp = await fetch(URL)
            let respJson = await resp.json()
            setData({data:respJson.data.statistics})
          }
      
          load()
        }, [])
      
        return data
      }
      

      你可以像这样使用

      export default function App(){
          const data = useApi()
      
          return (
              <View>
                  <ScrollView style={styles.center}>
                  <Text>{data.time}</Text>
                  </ScrollView>
              </View>
          )
      } 
      

      【讨论】:

      • useApi返回错误(如果有的话)可能是个好主意
      • 我已经用新问题更新了我的问题:c
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-03
      • 1970-01-01
      • 2019-03-10
      • 1970-01-01
      • 2019-01-07
      相关资源
      最近更新 更多