Relay抱怨片段变量,但没有片段有变量

时间:2016-09-27 19:42:30

标签: graphql relayjs

我正在学习接力,我开始工作,但有时感觉就像偶然一样:)

如果我在这里犯了初学者的错误,我很抱歉,我已经阅读了手册和所有的例子,但我似乎无法绕过这一切。

无论如何,我现在有以下问题。

我的架构如下所示:

{
    viewer(token:$anAuthToken) {
        actor {
          id,
          email,
          ...
        }
    }
}

所有数据都在{viewer}下访问,后者负责身份验证。演员领域只是其中之一。

Actor是UserType的实例,是当前登录的用户。

我想要一个理智的组件层次结构,其中顶级组件仅将用户作为props(并为其所需的属性提供片段)。但据Relay说,我做得不对,而且我不确定我做错了什么。

我的代码看起来像这样(此刻非常混乱,因为我测试了一些东西):

class UserRegistrationPage extends React.Component {

    render() {
        const user = this.props.user;
        return (
            <View>
                <Text>Email: {user.email}</Text>
            </View>
        );
    }

    submit(model) {
        const user = this.props.user;

        this.props.relay.commitUpdate(
            new UpdateUserMutation({
                id: user.id,
                ...model
            }, {
                onSuccess: response => {
                    console.log("SUCCESS!");
                    console.log(response);
                },
                onFailure: () => {
                    console.log("FAIL!");
                }
            }));
    }

}

UserRegistrationPage = Relay.createContainer(UserRegistrationPage, {
    fragments: {
        user: () => Relay.QL`
            fragment on User {
                email
            }
        `,
    },
});

//////////////////////////////

class UserRegistrationViewer extends React.Component {

    render() {
        return <UserRegistrationPage user={this.props.actor} />
    }

}

UserRegistrationViewer = Relay.createContainer(UserRegistrationViewer, {
    fragments: {
        actor: () => Relay.QL`
            fragment on Viewer {
                actor {
                    ${UserRegistrationPage.getFragment('user')},
                }
            }
        `,
    },
});

/////////////////////////////////

class QueryConfig extends Relay.Route {
    static routeName = 'UserRegistrationRoute';
    static prepareParams = routeConfigParamsBuilder;
    static queries = {
        actor: (Component) =>
            Relay.QL`
                     query {
                        viewer(token:$token) {
                            ${Component.getFragment('actor')},
                        }
                     }
        `,
    };
}

export const UserRegistrationPageComponent = (parentProps) => {
    return (
        <Relay.Renderer
            environment={Relay.Store}
            Container={UserRegistrationViewer}
            queryConfig={new QueryConfig()}
            render={({done, error, props, retry, stale}) => {
        if (error) {
          return <View><Text>Error!</Text></View>;
        } else if (props) {
          return <UserRegistrationViewer {...parentProps} {...props} />;
        } else {
          return <View><Text>Loading...</Text></View>;
        }
      }}
        />
    )
};

我收到以下错误。

  

警告:RelayContainer:组件UserRegistrationPage已呈现   变量与用于获取片段的变量不同   user。该片段是使用变量(not fetched)获取的,但是   使用变量{}进行渲染。这可以表示两个中的一个   可能性:     - 父级在查询中设置了正确的变量 - UserRegistrationPage.getFragment('user', {...}) - 但没有通过   渲染组件时的相同变量。一定要告诉   组件通过将它们作为props传递来使用哪些变量:   <UserRegistrationPage ... />。     - 您故意将虚假数据传递给此组件,在这种情况下忽略此警告。

所以我有几个问题。

1)为什么我会收到该错误,如何解决? 我不明白为什么当没有任何片段有任何变量时它会抱怨片段变量。

2)我怎样才能使UserRegistrationPage获得this.props.user? 我应该创建一个映射查询响应的组件树层次结构吗? 在某些时候我有this.props.actor.user,但我不希望组件知道查询响应结构,只知道它感兴趣的对象。

3)查询的名称是否以某种方式与片段名称相结合?

非常欢迎任何帮助,改进建议,提示和答案,我开始在这里撞墙:)

1 个答案:

答案 0 :(得分:5)

我终于明白了之前没有找到的一些细节。 我会在这里发布它们,以防它帮助其他任何正在努力接收Relay的人。

class QueryConfig extends Relay.Route {
    static routeName = 'UserRegistrationRoute';
    static prepareParams = routeConfigParamsBuilder;
    static queries = {
        actor: (Component) =>
            Relay.QL`
                     query {
                        viewer(token:$token) {
                            ${Component.getFragment('actor')},
                        }
                     }
        `,
    };
}

这里的查询在命名&#34;演员&#34;时会产生误导,因为它不会返回演员。它返回查询的根,即查看者。 此外,包含的片段是供观看者使用的,而不是演员。

让我们更新它。

class QueryConfig extends Relay.Route {
    static routeName = 'UserRegistrationRoute';
    static prepareParams = routeConfigParamsBuilder;
    static queries = {
        viewer: (Component) =>
            Relay.QL`
                     query {
                        viewer(token:$token) {
                            ${Component.getFragment('viewer')},
                        }
                     }
        `,
    };
}

完成。让我们看看第一个容器有什么问题。

UserRegistrationViewer = Relay.createContainer(UserRegistrationViewer, {
    fragments: {
        actor: () => Relay.QL`
            fragment on Viewer {
                actor {
                    ${UserRegistrationPage.getFragment('user')},
                }
            }
        `,
    },
});

同样的事情,名字有误导性。此容器不会将actor提供给组件,它会为查看器提供信息。

让我们更新它。

UserRegistrationViewer = Relay.createContainer(UserRegistrationViewer, {
    fragments: {
        viewer: () => Relay.QL`
            fragment on Viewer {
                actor {
                    ${UserRegistrationPage.getFragment('user')},
                }
            }
        `,
    },
});

所以,这里只更改了片段的名称。

现在,UserRegistrationViewer组件获得了一个prop&#34; viewer&#34; (由片段指定),类型为ViewerType。我们知道观众包含&#34;演员&#34;这是UserType的一个实例。 UserRegistrationPage需要一个prop&#34; user&#34;这是UserType的,由其片段指定。

因此,让我们更新组件。

class UserRegistrationViewer extends React.Component {

    render() {
        return <UserRegistrationPage user={this.props.viewer.actor} />
    }

}

现在我们有一个不了解查询响应层次结构的UI组件,一切正常!

我仍然不确定为什么我会遇到这个错误:)

希望这可以帮助别人!