从RN中的Firebase提取后,this.setState不会更新dataSource状态

时间:2018-10-03 15:06:32

标签: reactjs firebase react-native firebase-realtime-database state

在componentDidMount中,我输入了一个从Firebase中获取一些数据的函数,每次用户想要再次获取时都可以调用该函数。

问题是第一次获取不会更新。制作完之后,我想更新dataSource的数组,但不会更新它。它会通过加载旋转状态进行更新。

以下是代码:

    constructor(props) {
    super(props);

    const rowHasChanged = (r1, r2) => r1 !== r2
    // DataSource configured
     ds = new ListView.DataSource({ rowHasChanged })

    this.state = { 
        isLoading: true,
        dataSource: ds,
    };
}

componentDidMount() {
    this.fetchGroups()     
}
    fetchGroups() {
    firebase.database().ref('groups/numbers').once("value", (snap) => {
        snap.forEach((snapshot) => {
            firebase.database().ref('groups/' + snapshot.val()).once('value').then((snapshot) => {
                getparticipant = snapshot.val().participant
            var instantPrice
                switch (true) {
                    case (getparticipant <= 3):
                        instantSpace= snapshot.val().spaceOne
                        break;
                    case (getparticipant <= 10):
                        instantSpace= snapshot.val().spaceTwo
                        break;
                    case (getparticipant <= 20):
                        instantSpace= snapshot.val().spaceThree
                        break;
                    case (getparticipant > 20):
                        instantSpace= snapshot.val().spaceFourth
                        break;
                }
            dataObject.push({
                title: snapshot.val().type + ' ' + snapshot.val().brand,
                groupId: snapshot.val().groupID,
                description: snapshot.val().model,
                icon: snapshot.val().icon,
                partners: snapshot.val().participant,
                finalDate: snapshot.val().timeMerge,
                space: instantSpace,
                photo: snapshot.val().adminPhoto
                })
            }) 
        })
    }).then(() => {
        console.log(dataObject)
        this.setState({
            dataSource: ds.cloneWithRows(dataObject),
            isLoading: false
        })
        console.log(this.state.isLoading)
        console.log(this.state.dataSource)
    })
}

3 个答案:

答案 0 :(得分:3)

setStateasynchronous operation。因此,您不会马上拥有它的最新价值。

如果需要访问其最新更改,可以使用:

this.setState({
  dataSouce: ds.cloneWithRows(dataObject),
  isLoading: false,
}, () => {
  console.log(this.state.isLoading)
  console.log(this.state. dataSource)
})

const asyncOperation = () => new Promise(resolve => setTimeout(resolve, 2000))

class App extends React.Component {
  constructor() {
    super()

    this.state = {
      loading: false,
      counter: 0
    }

    this.handleClick = this.handleClick.bind(this)
  }

  handleClick() {
    this.setState({ loading: true })
    
    asyncOperation()
      .then(() => {
        console.log('Current state value:', this.state.counter)
        
        this.setState({
          counter: this.state.counter + 1,
          loading: false,
        }, () => {
          console.log('New state value:', this.state.counter)
        })
      })
  }

  render() {
    return (
      <div>
        <button onClick={this.handleClick}>
          Click-me
        </button>
        <p>Counter: {this.state.counter}</p>
        {this.state.loading && <p>Loading...</p>}
      </div>
    )
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

答案 1 :(得分:0)

尝试使用空白列表来初始化您的状态:

this.ds = new ListView.DataSource({
    rowHasChanged: (row1, row2) => row1 !== row2
});

this.state = { 
    dataSource: this.ds.cloneWithRows([]),
    isLoading: true
};

请注意[]函数内部的空白cloneWithRows

然后,创建一个新数组,并在获取数据时将其推送到新数组,并使用Object.assign方法更新状态。 像这样:

fetchGroups() {
    var dataObject = []

    firebase.database().ref('groups/numbers').once("value", (snap) => {
        snap.forEach((snapshot) => {
            firebase.database().ref('groups/' + snapshot.val()).once('value').then((snapshot) => {
                getparticipant = snapshot.val().participant;
                var instantSpace;
                switch (true) {
                    case (getparticipant <= 3):
                        instantSpace= snapshot.val().spaceOne
                        break;
                    case (getparticipant <= 10):
                        instantSpace= snapshot.val().spaceTwo
                        break;
                    case (getparticipant <= 20):
                        instantSpace= snapshot.val().spaceThree
                        break;
                    case (getparticipant > 20):
                        instantSpace= snapshot.val().spaceFourth
                        break;
                }

                dataObject.push({
                    title: snapshot.val().type + ' ' + snapshot.val().brand,
                    groupId: snapshot.val().groupID,
                    description: snapshot.val().model,
                    icon: snapshot.val().icon,
                    partners: snapshot.val().participant,
                    finalDate: snapshot.val().timeMerge,
                    price: instantPrice,
                    photo: snapshot.val().adminPhoto
                });

                // Update the state
                this.setState({ 
                   dataSource: this.ds.cloneWithRows(Object.assign({}, dataObject)) 
                });
            });
        });
    });
}

答案 2 :(得分:0)

再次遇到此问题后,我出于专业原因进行了搜索,这就是答案:JavaScript中的对象指向内存中的位置,然后其他对象将值保存在内存中,因此可以将值复制到新的内存位置,但是对象不是,它们引用创建对象时值在内存中的位置。因此,为了复制对象,Object.assign({},obj)可以完成这项工作,或者另一个更清洁的解决方案是编写{... obj}。