I'm using relay-modern. The following is getting me an error saying that $limit is not defined. How would I define the limit in the QueryRenderer? My thinking is that the limit was defined in Main.js but it looks like I need to somehow reference it in the QueryRenderer. I have a QueryRenderer in my app.js file that calls a fragment on another component, Main.js. app.js looks like this, Main.js follows:
```js
import '../style/style.css'
import React from 'react'
import ReactDOM from 'react-dom'
import { QueryRenderer, graphql } from 'react-relay'
import environment from './createRelayEnvironment'
import Main from './components/Main'
// change rootContainer to QueryRenderer
ReactDOM.render(
<QueryRenderer
environment={environment}
query={graphql`
query appQuery {
store {
...Main_store
}
}
`}
// variables={{limit: 100, query: ''}}
render={({ error, props}) => {
if (props) {
return <Main store={props.store} />
} else {
return <div>Loading</div>
}
}}
/>,
document.getElementById('react')
)
```
The ...Main_store fragment being called there is coming from this component, Main.js
```js
import React from 'react'
import {
createFragmentContainer,
createRefetchContainer,
graphql
} from 'react-relay'
import { debounce } from 'lodash'
import Business from './Business'
import CreateBusinessMutation from '../mutations/CreateBusinessMutation'
class Main extends React.Component {
constructor (props) {
super(props)
// TODO props.relay.* APIs do not exist on compat containers
// TODO needs manual handling
this._loadMore = debounce(this._loadMore, 300)
this.props.relay.Variables = { limit: 100, query: '' }
}
search = (e) => {
// TODO needs manual handling
this._loadMore({ query: e.target.value })
};
setLimit = (e) => {
// TODO needs manual handling
this._loadMore({ limit: Number(e.target.value) })
};
handleSubmit = (e) => {
e.preventDefault()
let onSuccess = () => {
$('#modal').closeModal()
}
let onFailure = (transaction) => {
const error = transaction.getError() || new Error('Mutation failed.')
console.error(error)
}
let name = this.refs.newName.value = ''
let url = this.refs.newUrl.value = ''
CreateBusinessMutation.commit(
this.props.relay.environment,
name,
url,
this.props.store
),
{onFailure, onSuccess}
}
componentDidMount () {
$('.modal-trigger').leanModal()
}
render () {
let content = this.props.store.businessConnection.edges.map(edge => {
return <Business key={edge.node.id} business={edge.node} />
})
return (
<div>
<div className="input-field">
<input id="search" type="text" onChange={this.search} />
<label htmlFor="search">Search All Businesses</label>
</div>
<div className="row">
<a className="waves-effect waves-light btn modal-trigger right light-blue white-text" href="#modal">Add New Business</a>
</div>
<ul>
{content}
</ul>
<div className="row">
<div className="col m3 hide-on-small-only">
<div className="input-field">
<select id="showing" className="browser-default"
// TODO props.relay.* APIs do not exist on compat containers
onChange={this.setLimit} defaultValue={this.props.relay.variables.limit}>
<option value="100">Show 100</option>
<option value="200">Show 200</option>
</select>
</div>
</div>
</div>
<div id="modal" className="modal modal-fixed-footer">
<form onSubmit={this.handleSubmit}>
<div className="modal-content">
<h5>Add New Business</h5>
<div className="input-field">
<input type="text" id="newName" ref="newName" required className="validate" />
<label htmlFor="newName">Name</label>
</div>
<div className="input-field">
<input type="url" id="newUrl" ref="newUrl" required className="validate" />
<label htmlFor="newUrl">Url</label>
</div>
</div>
<div className="modal-footer">
<button type="submit" className="waves-effect waves-green btn-flat green darken-3 white-text">
<strong>Add</strong>
</button>
<a href="#!" className="modal-action modal-close waves-effect waves-red btn-flat">Cancel</a>
</div>
</form>
</div>
</div>
)
}
_loadMore () {
// Increments the number of stories being rendered by 10.
const refetchVariables = fragmentVariables => ({
query: fragmentVariables.query,
limit: fragmentVariables.limit
})
this.props.relay.refetch(refetchVariables, null);
}
}
Main = createRefetchContainer(Main, {
/* TODO manually deal with:
initialVariables: {
limit: 100,
query: ''
}
*/
store: graphql`
fragment Main_store on Store {
id,
businessConnection(first: $limit, query: $query) {
edges {
node {
id,
...Business_business
}
}
}
}
`
},
graphql`
query MainRefetchQuery($limit: Int, $query: String) {
store {
...Main_store
}
}
`,
)
export default Main
```
This is the error in Chrome DevTools Network Tab on the query.
{
"errors": [
{
"message": "Variable \"$limit\" is not defined by operation \"appQuery\".",
"locations": [
{
"line": 10,
"column": 29
},
{
"line": 1,
"column": 1
}
]
},
{
"message": "Variable \"$query\" is not defined by operation \"appQuery\".",
"locations": [
{
"line": 10,
"column": 44
},
{
"line": 1,
"column": 1
}
]
},
{
"message": "Variable \"$showLikes\" is not defined by operation \"appQuery\".",
"locations": [
{
"line": 24,
"column": 27
},
{
"line": 1,
"column": 1
}
]
}
]
}
Any ideas would be greatly appreciated.(This mostly generated using the Relay Conversion Playbook) Thank you.
Updating - Adding schema in case that helps get answer:
```
type Business implements Node { # The ID of an object id: ID! name: String url: String state: String likesCount: Int createdAt: String }
# A connection to a list of items.
type BusinessConnection {
# Information to aid in pagination.
pageInfo: PageInfo!
# A list of edges.
edges: [BusinessEdge]
}
# An edge in a connection.
type BusinessEdge {
# The item at the end of the edge
node: Business
# A cursor for use in pagination
cursor: String!
}
input CreateBusinessInput {
name: String!
url: String!
clientMutationId: String
}
type CreateBusinessPayload {
businessEdge: BusinessEdge
store: Store
clientMutationId: String
}
type Mutation {
createBusiness(input: CreateBusinessInput!): CreateBusinessPayload
thumbsUp(input: ThumbsUpInput!): ThumbsUpPayload
}
# An object with an ID
interface Node {
# The id of the object.
id: ID!
}
# Information about pagination in a connection.
type PageInfo {
# When paginating forwards, are there more items?
hasNextPage: Boolean!
# When paginating backwards, are there more items?
hasPreviousPage: Boolean!
# When paginating backwards, the cursor to continue.
startCursor: String
# When paginating forwards, the cursor to continue.
endCursor: String
}
type Query {
# Fetches an object given its ID
node(
# The ID of an object
id: ID!
): Node
store: Store
}
type Store implements Node {
# The ID of an object
id: ID!
businessConnection(after: String, first: Int, before: String, last: Int, query: String): BusinessConnection
}
input ThumbsUpInput {
businessId: String
clientMutationId: String
}
type ThumbsUpPayload {
business: Business
clientMutationId: String
}
```
QueryRenderer can take a variables
prop. Try this:
<QueryRenderer
// ...
variables={{
limit: 10,
}}
// ...
/>
Now you can reference $limit
in any fragment children of the QueryRenderer
query.
If you need to change the value of $limit
and refetch, use createRefetchContainer
and call the refetch
method.
This GitHub comment addresses the issue, and will be incorporated into the Relay Modern documentation.
Example available here