Relay报错fragment变量,但是没有一个fragment有变量

Posted

技术标签:

【中文标题】Relay报错fragment变量,但是没有一个fragment有变量【英文标题】:Relay complains about fragment variables, but none of the fragments have variables 【发布时间】:2017-02-05 13:55:32 【问题描述】:

我正在学习 Relay,我得到了它的工作,但有时感觉就像是偶然的 :)

如果我在这里犯了初学者的错误,我很抱歉,我已经阅读了手册和所有示例,但我似乎无法全部理解。

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

我的架构如下所示:


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

所有数据都在  viewer 下访问,它负责身份验证。 actor 字段只是众多字段之一。

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

我想要一个健全的组件层次结构,其中***组件仅将用户作为道具(并为其所需的属性提供片段)。但根据 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', ...) - 但没有通过 渲染组件时使用相同的变量。一定要告诉 组件通过将它们作为道具传递来使用哪些变量: &lt;UserRegistrationPage ... /&gt;。 - 您故意将虚假数据传递给此组件,在这种情况下忽略此警告。

所以我有几个问题。

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

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

3) 查询名称是否以某种方式与片段名称结合在一起?

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

【问题讨论】:

【参考方案1】:

我终于明白了一些我之前没有意识到的细节。 我会把它们贴在这里,以防它帮助其他在 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'),
                        
                     
        `,
    ;

这里的查询在命名为“actor”时会产生误导,因为它不返回actor。它返回查询的根,即查看器。 此外,包含的片段是供观众使用的,而不是供演员使用的。

让我们更新它。

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'),
                
            
        `,
    ,
);

同样的事情,名称具有误导性。这个容器不会向组件中提供演员,而是向查看者提供内容。

让我们更新它。

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

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

现在,UserRegistrationViewer 组件获得了一个 ViewerType 类型的道具“查看器”(由片段指定)。我们知道查看器包含“actor”,它是 UserType 的一个实例。 UserRegistrationPage 需要一个属于 UserType 的道具“用户”,由其片段指定。

所以让我们更新组件。

class UserRegistrationViewer extends React.Component 

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


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

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

希望这可以帮助别人!

【讨论】:

以上是关于Relay报错fragment变量,但是没有一个fragment有变量的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在没有 GraphQL 的情况下使用 Relay?

关于getsupportFragmentManager报错

初识OpenGL 片段着色器(Fragment Shader)

初识OpenGL 片段着色器(Fragment Shader)

从外部存储中检索 Relay 查询片段的变量

MySQL多源复制报错,在线更改relay_log_info_repository,master_info_repository参数