使React Redux Firebase异步

时间:2018-05-01 19:56:38

标签: reactjs firebase redux react-redux

大家好!

我在reduxfirebase时遇到了一些问题。是否必须将路由器放到项目的根组件中?

我的一些工作非常适合这个系统,但不是asynchronous函数,主要是firebase的函数。

这篇文章基本上是关于firebase.[objects]的放置方式和位置,以便始终正确阅读。官方文件不是很清楚明确。

我提醒你我是firebase 的新手。

我尝试将它们放在反应循环函数中(例如componentDidMount(),...),因为渲染后会触发一些,但没有任何操作。

基本上,这就是我所做的:

  

Service.jsx

function getAll() {
    // I had saved some values in the localStorage
    const uid = JSON.parse(localStorage.getItem('user')).uid;

    // Here the reference to appropriate child in the database
    const dbRef = firebase.database().ref().child('events');

    // Choosing the user with appropriate's is
    const userRef = dbRef.child(uid);

    // An array to save fetched values
    let answer = [];

    // Created a listener
    userRef.on('value', snap => {
        let rx = snap.val();
        for (let item in snap.val()) {
            answer.push(rx[ item ]);
        }

        // Return a promise for the actions
        return Promise.resolve({
            events: answer
        });
    });

    return Promise.resolve({
        events: answer
    });

}
  

Reducer.jsx

export function events(state = { events: [] }, action) {
    //    --------> Get all
    case eventConstants.GET_ALL_REQUEST:
        return {
            ...state,
            managingEvent: true,
        };
    case eventConstants.GET_ALL_SUCCESS:
        return {
            ...state,
            events: action.events
        };
    case eventConstants.GET_ALL_FAILURE:
        return state;
    default:
        return state
    }
}
  

Action.jsx

function getAll() {
    return dispatch => {
        dispatch(request());

        eventService.getAll()
            .then(
                ans => {
                    dispatch(success(ans.events));
                },
                error => {
                    dispatch(failure(error));
                    dispatch(alertActions.error(error));
                }
            );
    };

    function request() {
        return { type: eventConstants.GET_ALL_REQUEST }
    }

    function success(events) {
        return { type: eventConstants.GET_ALL_SUCCESS, events }
    }

    function failure(error) {
        return { type: eventConstants.GET_ALL_FAILURE, error }
    }
}

GROB:

这就是我所做的。现在我正在尝试做:使用store.dispatch(Action.getAll())检索数据,因为我在搜索组件中使用这些数据。我以这种方式使用它们:

  

搜索

// usual imports here, connect inculed
import React, { Component } from 'react';
import { connect } from 'react-redux';

class SearchPage extends Component {

    // So I first used the constructor
    constructor(props){
        this.props.dispatch(Action.getAll());
    }

    componentDidMount() {
        // Then here... an same for all others methods of react lifecycle
        this.props.dispatch(Action.getAll());
    }

    render() {

    // TODO Don't forget the translation
    let { translate, events } = this.props;

    ....

    const table = (
        <Table hover>
            {tableHeader}
            <tbody>
            {events.map(item =>
                <tr key={item.key}>
                    <th scope="row">{item.key}</th>
                    <td>{item.name}</td>
                    <td>{item.startDate}</td>
                    <td>{item.endDate}</td>
                </tr>
            )}
            </tbody>
        </Table>
    );
...
}


const mapStateToProps = (state) => {
    const { events } = state.events;
    const translate = getTranslate(state.locale);
    return {
        events,
        translate,
    };
}

const connectedPage = connect(mapStateToProps)(SearchPage);
export { connectedPage as SearchPage };

商标:

有时它会被罚款,然后当我在线更新数据库然后重新渲染时,它说event为空或未定义,我可以理解,因为Reducer.js的过渡。

But what should I do now ?现在是我的问题。

感谢您阅读本文,感谢您的帮助。

:)

2 个答案:

答案 0 :(得分:2)

这里的问题是服务中的getAll函数不会等待监听器完成。因此,答案变量将始终为[]

解决方案是返回new promise instance,只有在从firebase接收数据后才能解析。

更新了Service.jsx

function getAll () {
  // I had saved some values in the localStorage
  const uid = JSON.parse(localStorage.getItem('user')).uid;

  // Here the reference to appropriate child in the database
  const dbRef = firebase.database().ref().child('events');

  // Choosing the user with appropriate's is
  const userRef = dbRef.child(uid);

  // An array to save fetched values
  const answer = [];
  return new Promise((resolve) => {
    // Created a listener
    userRef.on('value', (snap) => {
      const rx = snap.val();
      for (const item in snap.val()) {
        answer.push(rx[item]);
      }

      // Return a promise for the actions
      resolve({
        events: answer
      });
    });
  });
}

答案 1 :(得分:1)

我相信,如果事件的提取尚未完成,则在Services.jsx上的getAll()(return Promise...之外)结束时的userRef.on('value'...会导致函数getAll返回undefined。我会像这样重构Service.jsx(Firebase方法已经返回promise,所以你可以直接返回它们):

function getAll() {
    const uid = JSON.parse(localStorage.getItem('user')).uid;
    const dbRef = firebase.database().ref().child('events');
    const userRef = dbRef.child(uid);

    let answer = [];
    return userRef.on('value', snap => {
      snapshot.forEach((snap) => answer.push(snap.val())); 
      return {
        events: answer
      };
    });
}

您可以尝试的另一种方法是创建一个不呈现任何内容的特殊组件,仅负责在componentDidMount上附加firebase侦听器并在componentWillUnmount上删除它(类似下面的代码),然后将这个特殊组件导入到你的SearchPage.jsx。

class FirebaseListenToEvents extends Component {
  componentDidMount() {
    const uid = JSON.parse(localStorage.getItem('user')).uid;
    const dbRef = firebase.database().ref().child('events');    
    this.userRef = dbRef.child(uid);

    this.userRef.on('value', (snap) => {
      this.props.onUpdateEvent(snap.key, snap.val());
    });
  }

  componentWillUnmount() {
    this.userRef.off('value');
  }

  render() {
    return null;
  }
}

我不确定哪种方法最适合您,但我希望这能为您提供一些有关如何处理Firebase&amp; amp;反应。这article似乎也比我更好地解释了它。如果您有问题,请在评论中问我。祝你好运!