React - 在状态

时间:2016-11-21 08:52:43

标签: javascript reactjs firebase firebase-realtime-database state

我正在开发一个React应用程序,该应用程序从Google Firebase上的数据库中获取数据。

数据库以这种方式组织:

users {
    user 1 {
        name
        surname
        ... 
    }
    user 2 {
        name
        surname
        ...
    }
}

我如何在React中检索数据:

我从网址获取位置和工具来过滤搜索结果(现在只使用位置,但想同时使用),并且我成功设法在控制台中打印对象。

componentWillMount(){
    const searchResults = FBAppDB.ref('users');

    let location = this.props.location;
    let instrument = this.props.instrument;

    let profiles = [];
    searchResults.orderByChild('location').equalTo(location).on('value', (snap) => {
        let users = snap.val();
        Object.keys(users).map((key) => {
            let user = users[key];
            console.log(user);
            profiles.push(user);
        });
    });

    // this.setState({users: profiles[0]});
}

对象的控制台输出:

Object {name: "Whatever", surname: "Surrname", ... }

我似乎失败的做法是在状态中保存这些对象(可能不止一个),这样我就可以在用户更改页面上的其他过滤器时更新视图。

我试过setState实际用户,但状态结果为空,任何想法?

除了写作之外,从州获取数据的最佳方法是什么?如何在状态中循环对象?

由于

修改

这就是我的渲染函数的样子:

render(){
    return(
        <Row>
            {
                Object.keys(this.state.users).map(function (key) {
                    var user = this.state.users[key];
                    return <SearchResult user={user} />
                })
            }
        </Row>
    );
}

我试图直接打印this.state.users,但它不起作用。因此,我尝试提出一个(非工作)解决方案。我很抱歉这里有任何noob错误。

2 个答案:

答案 0 :(得分:1)

  

我尝试将setState设置为实际用户,但状态结果为空,任何   想法?

这是因为您的数据库操作searchResult 异步,并且JavaScript不会让同步代码等到异步代码完成。

在您的代码中,如果启用注释setState调用,则在异步代码等待响应时将执行该代码。

您需要setState内部:

searchResults.orderByChild('location').equalTo(location).on('value', (snap) => {
    let users = snap.val();
    const profiles = Object.keys(users).map((key) => users[key]);
    this.setState({ users: profiles[0] });
});

每当您想要在异步代码之后执行某些操作时,请将其放在callback内(到异步fn)或使用Promise

  

从州获取数据的最佳方法是什么?如何在状态中循环对象?

setState也可以是异步的。但是您将在下一次渲染时获得新的更新状态。因此,在render()内,您可以在状态users中访问this.state.users并使用它执行操作。

更新

componentWillMount(){
    const searchResults = FBAppDB.ref('users');
    const location = this.props.location;
    const instrument = this.props.instrument;

    searchResults.orderByChild('location').equalTo(location).on('value', (snap) => {
        const users = snap.val();
        const profiles = Object.keys(users).map((key) => users[key]);

        // previously we were setting just profiles[0]; but I think you need 
        // the entire list of users as an array to render as search results
        this.setState({ users: profiles }); // set the whole data to state
    });
}


render(){
    const users = this.state.users || []; // note that this.state.users is an array

    return(
        <Row>
            {
              users.length > 0 
              ? users.map((user) => <SearchResult user={user} />)
              : null
            }
        </Row>
    );
}

答案 1 :(得分:0)

尝试在Object.keys(...)之后将setState放在.on(()=&gt; ...)中。它是对服务器的异步调用,对吧?我想在调用服务器之后立即调用setState,但在检索任何数据之前。