Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
150 views
in Technique[技术] by (71.8m points)

reactjs - How can I chain asynchronous Firebase updates in my React app?

React & Firebase newbie here. I have a React component that needs to look up some stuff in Firebase before rendering. My database design requires first getting the correct doohick ids and subsequently looking up the doohick details, but I'm not sure how to do that with the asynchronous nature of Firebase database access. This doesn't work:

class Widget extends React.Component {
    componentDidMount() {
        firebase.database().ref(`/users/${username}/doohick-ids`).on('value', snapshot => {
            this.setState({doohick_ids: doohick_ids});
        });

        this.state.doohick_ids.forEach(id => {  
            // ids don't actually exist at this point outside the callback
            firebase.database().ref(`/doohick-details/${id}`).on('value', snapshot => {
                // update state
            });         
        });

    render() {
        if (this.state.doohick-ids) {
            return null;
        } else {
            // render the Doohick subcomponents
        } 
    }
}

I can think of a few solutions here, but none that I like. What's the recommended way to chain together Firebase calls, or perhaps redesign this to eliminate the problem?

question from:https://stackoverflow.com/questions/65646130/how-can-i-chain-asynchronous-firebase-updates-in-my-react-app

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I think you should split one component Widget to two WidgetList and WidgetItem.

WidgetItem

subscribe and unsubscribe to firebase.database().ref(/doohick-details/${id})

class WidgetItem extends React.Component {
  static propTypes = {
    id: PropTypes.string.isRequired,
  }

  constructor(props) {
    super(props);

    this.state = {};
    this.dbRef = null;

    this.onValueChange = this.onValueChange.bind(this);
  }

  componentDidMount() {
    const { id } = this.props;
    this.dbRef = firebase.database().ref(`/doohick-details/${id}`);

    this.dbRef.on('value', this.onValueChange);
  }

  componentWillUnmount() {
    this.dbRef.off('value', this.onValueChange);
  }

  onValueChange(dataSnapshot) {
    // update state
    this.setState(dataSnapshot);
  }

  render() {
    return (
      <pre>{JSON.stringify(this.state, null, 2)}</pre>
    );
  }
}

WidgetList

subscribe and unsubscribe to firebase.database().ref(/users/${username}/doohick-ids)

class WidgetItem extends React.Component {
  constructor(props) {
    super(props);

    this.state = { doohick_ids: [] };
    this.dbRef = null;

    this.onValueChange = this.onValueChange.bind(this);
  }

  componentDidMount() {
    // Note: I've just copied your example. `username` is undefined.
    this.dbRef = firebase.database().ref(`/users/${username}/doohick-ids`);

    this.dbRef.on('value', this.onValueChange);
  }

  componentWillUnmount() {
    this.dbRef.off('value', this.onValueChange);
  }

  onValueChange(dataSnapshot) {
    this.setState({ doohick_ids: dataSnapshot });
  }

  render() {
    const { doohick_ids } = this.state;

    if (doohick_ids.length === 0) {
      return 'Loading...';
    }

    return (
      <React.Fragment>
        {doohick_ids.map(id => <WidgetItem key={id} id={id} />)}
      </React.Fragment>
    );
  }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...