SO Relay QueryRenderer - TypeError: this.props.render is not a function

Multi tool use
Multi tool use


SO Relay QueryRenderer - TypeError: this.props.render is not a function



I have a project in React using Redux and Relay. The client connects to an API Server using GraphQL. I was trying to use the component QueryRenderer and I'm getting the following error:


TypeError: this.props.render is not a function
render
src/react-landing/node_modules/react-relay/lib/ReactRelayQueryRenderer.js:164

161 | if (process.env.NODE_ENV !== 'production') {
162 | deepFreeze(renderProps);
163 | }
> 164 | return this.props.render(renderProps);
165 | };
166 |
167 | return ReactRelayQueryRenderer;

View compiled
finishClassComponent
src/react-landing/node_modules/react-dom/cjs/react-dom.development.js:13193

13190 | } else {
13191 | {
13192 | ReactDebugCurrentFiber.setCurrentPhase('render');
> 13193 | nextChildren = instance.render();
13194 | if (debugRenderPhaseSideEffects || debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictMode) {
13195 | instance.render();
13196 | }

View compiled
updateClassComponent
src/react-landing/node_modules/react-dom/cjs/react-dom.development.js:13155

13152 | } else {
13153 | shouldUpdate = updateClassInstance(current, workInProgress, renderExpirationTime);
13154 | }
> 13155 | return finishClassComponent(current, workInProgress, shouldUpdate, hasContext, renderExpirationTime);
13156 | }
13157 |
13158 | function finishClassComponent(current, workInProgress, shouldUpdate, hasContext, renderExpirationTime) {

View compiled
beginWork
src/react-landing/node_modules/react-dom/cjs/react-dom.development.js:13824

13821 | case FunctionalComponent:
13822 | return updateFunctionalComponent(current, workInProgress);
13823 | case ClassComponent:
> 13824 | return updateClassComponent(current, workInProgress, renderExpirationTime);
13825 | case HostRoot:
13826 | return updateHostRoot(current, workInProgress, renderExpirationTime);
13827 | case HostComponent:

View compiled
performUnitOfWork
src/react-landing/node_modules/react-dom/cjs/react-dom.development.js:15863

15860 | startBaseRenderTimer();
15861 | }
15862 |
> 15863 | next = beginWork(current, workInProgress, nextRenderExpirationTime);
15864 |
15865 | if (workInProgress.mode & ProfileMode) {
15866 | // Update "base" time if the render wasn't bailed out on.

View compiled
workLoop
src/react-landing/node_modules/react-dom/cjs/react-dom.development.js:15902

15899 | if (!isAsync) {
15900 | // Flush all expired work.
15901 | while (nextUnitOfWork !== null) {
> 15902 | nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
15903 | }
15904 | } else {
15905 | // Flush asynchronous work until the deadline runs out of time.

View compiled
callCallback
src/react-landing/node_modules/react-dom/cjs/react-dom.development.js:100

97 | // nested call would trigger the fake event handlers of any call higher
98 | // in the stack.
99 | fakeNode.removeEventListener(evtType, callCallback, false);
> 100 | func.apply(context, funcArgs);
101 | didError = false;
102 | }
103 |

View compiled
invokeGuardedCallbackDev
src/react-landing/node_modules/react-dom/cjs/react-dom.development.js:138

135 | // Synchronously dispatch our fake event. If the user-provided function
136 | // errors, it will trigger our global error handler.
137 | evt.initEvent(evtType, false, false);
> 138 | fakeNode.dispatchEvent(evt);
139 |
140 | if (didError) {
141 | if (!didSetError) {

View compiled
invokeGuardedCallback
src/react-landing/node_modules/react-dom/cjs/react-dom.development.js:187

184 | * @param {...*} args Arguments for function
185 | */
186 | invokeGuardedCallback: function (name, func, context, a, b, c, d, e, f) {
> 187 | invokeGuardedCallback$1.apply(ReactErrorUtils, arguments);
188 | },
189 |
190 | /**

View compiled
replayUnitOfWork
src/react-landing/node_modules/react-dom/cjs/react-dom.development.js:15310

15307 | // Replay the begin phase.
15308 | isReplayingFailedUnitOfWork = true;
15309 | originalReplayError = thrownValue;
> 15310 | invokeGuardedCallback$2(null, workLoop, null, isAsync);
15311 | isReplayingFailedUnitOfWork = false;
15312 | originalReplayError = null;
15313 | if (hasCaughtError()) {

View compiled
renderRoot
src/react-landing/node_modules/react-dom/cjs/react-dom.development.js:15962

15959 |
15960 | var failedUnitOfWork = nextUnitOfWork;
15961 | if (true && replayFailedUnitOfWorkWithInvokeGuardedCallback) {
> 15962 | replayUnitOfWork(failedUnitOfWork, thrownValue, isAsync);
15963 | }
15964 |
15965 | // TODO: we already know this isn't true in some cases.

View compiled
performWorkOnRoot
src/react-landing/node_modules/react-dom/cjs/react-dom.development.js:16560

16557 | // This root is already complete. We can commit it.
16558 | completeRoot(root, finishedWork, expirationTime);
16559 | } else {
> 16560 | finishedWork = renderRoot(root, expirationTime, false);
16561 | if (finishedWork !== null) {
16562 | // We've completed the root. Commit it.
16563 | completeRoot(root, finishedWork, expirationTime);

View compiled
performWork
src/react-landing/node_modules/react-dom/cjs/react-dom.development.js:16482

16479 | }
16480 | } else {
16481 | while (nextFlushedRoot !== null && nextFlushedExpirationTime !== NoWork && (minExpirationTime === NoWork || minExpirationTime >= nextFlushedExpirationTime)) {
> 16482 | performWorkOnRoot(nextFlushedRoot, nextFlushedExpirationTime, false);
16483 | findHighestPriorityRoot();
16484 | }
16485 | }

View compiled
performSyncWork
src/react-landing/node_modules/react-dom/cjs/react-dom.development.js:16454

16451 | }
16452 |
16453 | function performSyncWork() {
> 16454 | performWork(Sync, false, null);
16455 | }
16456 |
16457 | function performWork(minExpirationTime, isAsync, dl) {

View compiled
requestWork
src/react-landing/node_modules/react-dom/cjs/react-dom.development.js:16354

16351 |
16352 | // TODO: Get rid of Sync and use current time?
16353 | if (expirationTime === Sync) {
> 16354 | performSyncWork();
16355 | } else {
16356 | scheduleCallbackWithExpiration(expirationTime);
16357 | }

View compiled
scheduleWork$1
src/react-landing/node_modules/react-dom/cjs/react-dom.development.js:16218

16215 | !isWorking || isCommitting$1 ||
16216 | // ...unless this is a different root than the one we're rendering.
16217 | nextRoot !== root) {
> 16218 | requestWork(root, nextExpirationTimeToWorkOn);
16219 | }
16220 | if (nestedUpdateCount > NESTED_UPDATE_LIMIT) {
16221 | invariant(false, 'Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.');

View compiled
scheduleRootUpdate
src/react-landing/node_modules/react-dom/cjs/react-dom.development.js:16785

16782 | }
16783 | enqueueUpdate(current, update, expirationTime);
16784 |
> 16785 | scheduleWork$1(current, expirationTime);
16786 | return expirationTime;
16787 | }
16788 |

View compiled
updateContainerAtExpirationTime
src/react-landing/node_modules/react-dom/cjs/react-dom.development.js:16812

16809 | container.pendingContext = context;
16810 | }
16811 |
> 16812 | return scheduleRootUpdate(current, element, expirationTime, callback);
16813 | }
16814 |
16815 | function findHostInstance(component) {

View compiled
updateContainer
src/react-landing/node_modules/react-dom/cjs/react-dom.development.js:16839

16836 | var current = container.current;
16837 | var currentTime = recalculateCurrentTime();
16838 | var expirationTime = computeExpirationForFiber(currentTime, current);
> 16839 | return updateContainerAtExpirationTime(element, container, parentComponent, expirationTime, callback);
16840 | }
16841 |
16842 | function getPublicRootInstance(container) {

View compiled
./node_modules/react-dom/cjs/react-dom.development.js/ReactRoot.prototype.render
src/react-landing/node_modules/react-dom/cjs/react-dom.development.js:17122

17119 | if (callback !== null) {
17120 | work.then(callback);
17121 | }
> 17122 | updateContainer(children, root, null, work._onCommit);
17123 | return work;
17124 | };
17125 | ReactRoot.prototype.unmount = function (callback) {

View compiled
legacyRenderSubtreeIntoContainer/<
src/react-landing/node_modules/react-dom/cjs/react-dom.development.js:17262

17259 | if (parentComponent != null) {
17260 | root.legacy_renderSubtreeIntoContainer(parentComponent, children, callback);
17261 | } else {
> 17262 | root.render(children, callback);
17263 | }
17264 | });
17265 | } else {

View compiled
unbatchedUpdates
src/react-landing/node_modules/react-dom/cjs/react-dom.development.js:16679

16676 | isUnbatchingUpdates = false;
16677 | }
16678 | }
> 16679 | return fn(a);
16680 | }
16681 |
16682 | // TODO: Batching should be implemented at the renderer level, not within

View compiled
legacyRenderSubtreeIntoContainer
src/react-landing/node_modules/react-dom/cjs/react-dom.development.js:17258

17255 | };
17256 | }
17257 | // Initial mount should not be batched.
> 17258 | unbatchedUpdates(function () {
17259 | if (parentComponent != null) {
17260 | root.legacy_renderSubtreeIntoContainer(parentComponent, children, callback);
17261 | } else {

View compiled
render
src/react-landing/node_modules/react-dom/cjs/react-dom.development.js:17317

17314 | return legacyRenderSubtreeIntoContainer(null, element, container, true, callback);
17315 | },
17316 | render: function (element, container, callback) {
> 17317 | return legacyRenderSubtreeIntoContainer(null, element, container, false, callback);
17318 | },
17319 | unstable_renderSubtreeIntoContainer: function (parentComponent, element, containerNode, callback) {
17320 | !(parentComponent != null && has(parentComponent)) ? invariant(false, 'parentComponent must be a valid React Component') : void 0;

View compiled
./src/index.js
src/react-landing/src/index.js:15

12 | import '../node_modules/font-awesome/css/font-awesome.min.css';
13 |
14 |
> 15 | ReactDOM.render(
16 | <Provider store={ store }>
17 | <I18nextProvider i18n={ i18n }>
18 | <App />

View compiled
▶ 6 stack frames were collapsed.



This are the source files:



src/components/HomePage/Header/Header.jsx


import React from 'react';
import { connect } from "react-redux";
import { I18n } from 'react-i18next';
import { QueryRenderer } from 'react-relay';

import environment from '../../../relay/environment';
import featuredStores from './FeaturedStores';
import SearchBox from '../../SearchBox/SearchBox';

import './Header.css';


const mapStateToProps = state => {
return {
query: state.storeService.getAllFeatured()
};
};

const Header = ({ query }) => (
<I18n>
{
(t) => (
<div className="background">
<ul className="cb-slideshow">
<li><span>Image 01</span></li>
<li><span>Image 02</span></li>
<li><span>Image 03</span></li>
</ul>
<div className="banner">
<div className="container">
<div className="banner-info">
<h2>{ t('home-page.header.title') }</h2>
<p>{ t('home-page.header.description') }</p>
</div>
<div className="banner-grads">
<QueryRenderer environment={ environment } query={ query }> render={ featuredStores }></QueryRenderer>

<div className="clearfix"></div>

<SearchBox />
</div>
</div>
</div>
</div>
)
}
</I18n>
);

export default connect(mapStateToProps)(Header);



src/components/HomePage/Header/FeaturedStores.jsx


import React from 'react';
import Spinner from 'react-spinkit';

/**
* FeaturedStores component.
*/
export default ({ error, stores }) => {
if (error) {
return <div>Error!</div>;
}

if (!stores) {
return <Spinner name="line-scale" color="blue" />;
}

return (
<div>
{
stores.map((store, key) => {
return (
<div className="col-md-4 banner-grad" key={ key }>
<div className="banner-grad-img">
<img src={ store.image } alt={ store.name } />
<h4>{ store.name }</h4>
<p>
<span className="storeDescription">{ store.description }</span>
<br /> { store.address }, { store.city }
</p>
</div>
</div>
);
})
}
</div>
);
}



src/relay/services/StoreService.jsx


import storesQuery from '../queries/StoresQuery';
import featuredStoresQuery from '../queries/FeaturedStoresQuery';
import storeQuery from '../queries/StoreQuery';
import storesByMenuItemQuery from '../queries/StoresByMenuItemQuery';


/** Limit of stores per request. */
const LIMIT = 24

/**
* class :: StoreService
*
* Service for Store types.
*/
class StoreService {
/**
* Constructor.
*/
constructor() {
this.storesQuery = storesQuery;
this.storeQuery = storeQuery;
this.featuredStoresQuery = featuredStoresQuery;
this.storesByMenuItemQuery = storesByMenuItemQuery;
this.searchFrom404 = false
this.skipCounter = 0
}

/**
* Resets the skip counter.
*/
resetSkipCounter() {
this.skipCounter = 0
}

/**
* Gets all the stores using pagination.
*
* @returns {any} GraphQL query for retrieving the stores from the API server.
*/
getAll() {
this.skipCounter += LIMIT

return this.storesQuery;
}

/**
* Gets all the featured stores.
*
* @returns {any} GraphQL query for retrieving the featured stores from the API server.
*/
getAllFeatured() {
return this.featuredStoresQuery;
}

/**
* Gets an store from the API server by its URI.
*
* @returns {any} GraphQL query for retrieving the store from the API server.
*/
getStore() {
return this.storeQuery;
}

/**
* Gets all the stores from the API server that have the given item in their menues.
*
* @param {Boolean} searchFrom404 True if the search was performed from the SearchBox component.
* @returns {any} GraphQL query for retrieving the stores from the API server.
*/
getAllByMenuItem(searchFrom404) {
this.searchFrom404 = searchFrom404 || false

return this.storesByMenuItemQuery;
}
}

/**
* Singleton implementation.
*/
export default (function () {
/** StoreService instance reference. */
let instance = null

return {
/**
* Gets a unique instance of StoreService.
*
* @returns {StoreService} A unique instance of StoreService.
*/
getInstance: function () {
if (!instance) {
instance = new StoreService()
}
return instance
}
}
})()



src/relay/queries/FeaturedStoresQuery.js


import { graphql } from 'react-relay';


/**
* Gets all the featured stores.
*/
export default graphql`
query FeaturedStoresQuery {
featuredStores {
URI
name
category
address
city
image
}
}
`;



How can I solve this issue and render my component with QueryRenderer?





it's hard to figure out, but error is pointing in root index component error so try just simple component without translation and then simple component with translation, I dont think graphql relay is problem it might be t => render that is wrong but it might not... try simple versions first
– AlexGvozden
Jul 1 at 14:02




2 Answers
2



The translations was working just fine before adding Redux and Relay. Someone told me that Relay can manage centralized states so I'll try to remove Redux before trying something else. Maybe both together are collapsing the rendering.



The problem is solved now! I removed Redux and fixed that extra ">" between query and render props.



src/components/HomePage/Header/Header.jsx


import React, { Component } from 'react';
import { I18n } from 'react-i18next';
import { QueryRenderer } from 'react-relay';

import environment from '../../../relay/environment';
import query from '../../../relay/queries/FeaturedStoresQuery';
import featuredStores from './FeaturedStores';
import SearchBox from '../../SearchBox/SearchBox';

import './Header.css';


export default class Header extends Component {
/**
* Renders the component.
*
* @returns {string} The component's JSX code.
*/
render() {
return (
<I18n>
{
(t) => (
<div className="background">
<ul className="cb-slideshow">
<li><span>Image 01</span></li>
<li><span>Image 02</span></li>
<li><span>Image 03</span></li>
</ul>
<div className="banner">
<div className="container">
<div className="banner-info">
<h2>{ t('home-page.header.title') }</h2>
<p>{ t('home-page.header.description') }</p>
</div>
<div className="banner-grads">
<QueryRenderer environment={ environment } query={ query } render={ featuredStores } />

<div className="clearfix"></div>

<SearchBox />
</div>
</div>
</div>
</div>
)
}
</I18n>
);
}
}



I've also modified the rendering function. It seems that the second param has to be named as props literally. It can't be named differently! (stores was the named used before in my example code).



src/components/HomePage/Header/FeaturedStores.jsx


import React from 'react';
import Spinner from 'react-spinkit';

/**
* FeaturedStores component.
*/
export default ({ error, props }) => {
if (error) {
return <div>Error!</div>;
}

if (!props) {
return <Spinner name="line-scale" color="blue" />;
}

return (
<div>
{
props.featuredStores.map((store, key) => {
return (
<div className="col-md-4 banner-grad" key={ key }>
<div className="banner-grad-img">
<img src={ store.image } alt={ store.name } />
<h4>{ store.name }</h4>
<p>
<span className="storeDescription">{ store.description }</span>
<br /> { store.address }, { store.city }
</p>
</div>
</div>
);
})
}
</div>
);
}






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

tyjT,9gLdl xk,2,NCHohbYkWJDlJePp4KSBqN lzv8MJgGUf1p y b6UP0 paDUx3mD cq BCk iOGBBdmL9Oa,kPdPrRSfHY
sqbSl0o IBvb RQCJfyTKGJVjeKdV,8

Popular posts from this blog

Rothschild family

Cinema of Italy