relay-tools / relay-subscriptions

[Deprecated] Subscription support for Relay Classic

Home Page:https://facebook.github.io/relay/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Required context `subscriptions` was not specified

h3llh0und opened this issue · comments

Hi,

i want to try out the subscriptions. But i got some errors while trying. Maybe you can help me:

This is the Error:
"warning.js:45 Warning: Failed Context Types: Required context subscriptions was not specified in SubscriptionContainer(MessageList). Check the render method of Relay(props => ReactElement)."

After this "this.props.subscriptions" is undefined.

Here is the Code:

import React from 'react';
import Relay from 'react-relay';
import auth from '../authentication';
import MessageTitle from './MessageTitle';
import * as RelaySubscriptions from 'relay-subscriptions';

class MessageList extends React.Component {
    constructor() {
        super();
        this.getClassName = this.getClassName.bind(this);
    }

    componentDidMount() {
        const subscribe = this.props.subscriptions.subscribe;
        this._addSubscription = subscribe(
            new AddMessageSubscription({user: this.props.user}),
            'add_message'
        );
    }

    componentWillUnmount() {
        if (this._addSubscription) this._addSubscription.dispose();
    }


    getClassName(message) {
        var className = 'card';
        if (!message.isRead) {
            className += ' card-inverse card-danger';
        }
        return className;
    }

    markAsRead(message) {
        if (!message.isRead) {
            var onFailure = (transaction) => {
                var error = transaction.getError() || new Error('Mutation failed.');
                self.setState({errorMessage: error.source.errors[0].message});
                console.error(error);
            };

            var onSuccess = (response) => {
                console.log(response);
            };

            Relay.Store.commitUpdate(new readMessageMutation(
                {
                    message: message,
                    user: this.props.user
                }), {onFailure, onSuccess}
            );
        }

    }

    render() {
        return (
            <div id="accordion">
                {this.props.user.messages.map(message =>
                    <div className={this.getClassName(message)}>
                        <div className="card-block" role="tab" id={'heading' + message.messageId}>
                            <h5 className="card-title">
                                <a onClick={this.markAsRead.bind(this, message)} data-toggle="collapse"
                                   data-parent="#accordion" href={'#collapse' + message.messageId} aria-expanded="false"
                                   aria-controls={'collapse' + message.messageId}>
                                    <MessageTitle message={message}></MessageTitle>
                                </a>
                            </h5>
                        </div>
                        <div id={'collapse' + message.messageId} className="panel-collapse collapse" role="tabpanel"
                             aria-labelledby={'heading' + message.messageId}>
                            <div className="card-block">
                                <div dangerouslySetInnerHTML={{__html: message.message}}></div>
                            </div>
                        </div>
                    </div>
                )}
            </div>
        )
    }
}

class AddMessageSubscription extends RelaySubscriptions.Subscription {
    getSubscription() {
        return Relay.QL`subscription {
            addMessageSubscription {
                clientMutationId,
                user {
                    id
                    unreadMessageCount,
                    messages {
                        id,
                        messageId,
                        ${MessageTitle.getFragment('message')},
                        message,
                        isRead
                    }
                }
            }
        }`;
    }

    getVariables() {
        return {};
    }

    getConfigs() {
        return [{
            type: 'RANGE_ADD',
            parentName: 'user',
            parentID: this.props.user.id,
            connectionName: 'messages',
            rangeBehaviors: () => 'append',
        }];
    }
}

class readMessageMutation extends Relay.Mutation {
    getMutation() {
        return Relay.QL`mutation {readMessage}`;
    }

    getVariables() {
        return {messageId: this.props.message.messageId};
    }

    getConfigs() {
        return [
            {
                type: 'FIELDS_CHANGE',
                fieldIDs: {
                    user: this.props.user.id,
                    message: this.props.message.id
                }
            },
            {
                type: 'REQUIRED_CHILDREN',
                // Forces these fragments to be included in the query
                children: [Relay.QL`
                    fragment on readMessagePayload {
                        message{
                            id,
                            isRead
                        },
                        user {
                            id,
                            unreadMessageCount
                        }
                    }
                  `],
            }
        ];
    }

    getFatQuery() {
        return Relay.QL`
            fragment on readMessagePayload {
                message{
                    id,
                    isRead
                },
                user {
                    id,
                    unreadMessageCount
                }
            }
    `;
    }

    getOptimisticResponse() {
        return {
            user: {
                id: this.props.user.id,
                unreadMessageCount: this.props.user.unreadMessageCount - 1
            },
            message: {
                id: this.props.message.id,
                isRead: true
            }
        };
    }
}

export default Relay.createContainer(RelaySubscriptions.createSubscriptionContainer(MessageList), {
    fragments: {
        user: () => Relay.QL`
        fragment on User {
            id,
            unreadMessageCount,
            messages {
                id,
                messageId,
                ${MessageTitle.getFragment('message')},
                message,
                isRead
            }
        }
    `,
    }
});

Maybe someone can help?

Greetings Ronny

I think the problem is that you are missing to provide a SubscriptionProvider component at the top of the component tree.

It's important to note that all SubscriptionContainers needs to be rendered under the SubscriptionProvider.
Can you verify that you have a <SubscriptionProvider subscribe={} environment={}></SubscriptionProvider> somewhere at the top of the tree?
In the todo app I have placed it in the Root component which also is the component that handles all the communication with the server.
https://github.com/edvinerikson/relay-subscriptions/blob/master/examples/todo/js/components/Root.js#L67-L69

Also, please note that in your getSubscription method please include the __typename field on new nodes that gets added to the store, otherwise Relay can't handle the record correctly.

Thx, now it woks 👍