使用componentWillMount和componentDidMount来反应Native setState(...)警告

时间:2016-02-12 16:07:26

标签: react-native

我从反应原生开始,在我的项目中,我达到了一切可行的地步,但是有这个警告:

Warning: setState(...): Can only update a mounted or mounting component.

所以,我已经查看了几个QA,尝试了一些解决方案(更改了来自setState()componentWillMount的{​​{1}}来电)但是...警告始终存在。

以下是代码的一部分:

componentDidMount

REQUEST_URL = 'http://url/users.php'; (...) module.exports = React.createClass({ getInitialState: function() { return { uid: null, bid: null, username: null, } }, componentDidMount: function() { this.fetchData(); }, fetchData: function() { fetch(REQUEST_URL) .then( (response) => response.json() ) .then( (json) => { console.log('setState called'); this.setState({ uid: json.users[0].user_id, bid: json.users[0].building_id, username: json.users[0].username }); }) .done(); }, render: function() { if (!this.state.uid) { //user is not defined console.log('not rendered'); return <Text>chargement...</Text> } // else console.log('rendered'); var userId = this.state.uid; var buildingId = this.state.bid; var username = this.state.username; return ( <View style={styles.content}> <Text style={styles.label}>User Id</Text> <Text>{userId}</Text> <Text style={styles.label}>Building Id</Text> <Text>{buildingId}</Text> <Text style={styles.label}>Username</Text> <Text>{username}</Text> </View> ) }, }); 返回json内容类型。

任何线索?

感谢名单。

1 个答案:

答案 0 :(得分:2)

The problem may be that react re-mounts certain components multiple times in one render (think that has something to do with the representation of initial values, could not find the question here), therefore your state would be set to a component that is not mounted.

If you set your state in a decoupled timeout that can be cleared when the component unmounts, you avoid setting state on a unmounted component.

componentDidMount() {
  this.mounted = true;
  // this.fetchTimeout = setTimeout(()=>{
    this.fetchData();
  // });
},
componentWillUnmount() {
  // clearTimeouts(this.fetchTimeout);
  this.mounted = false;
},
fetchData() {
    fetch(REQUEST_URL)
        .then( (response) => response.json() )
        .then( (json) => {
            console.log('setState called');
            if (this.mounted === true){
               this.setState({
                  uid: json.users[0].user_id,
                  bid: json.users[0].building_id,
                  username: json.users[0].username
              });
            }
        })
        .done();
},

I still don't know if we are supposed to use TimerMixins but this way works without those. (TimerMixins take care of clearing any timeout or interval set in the component)

EDIT: update sample to only call setState of the component is still mounted. I do not know if there is a better way, but as far as I know until now you can not cancel a fetch request.