The prop `push` is marked as required - javascript

I'm getting this warning when i call the ReactDOM.render() method:
Failed prop type: The prop push is marked as required in
Connect(Detail), but its value is undefined
This is the render call:
const render = Component => {
const appElement = document.getElementById('app');
ReactDOM.render(
<AppContainer>
{Component}
</AppContainer>,
appElement
);
};
And this is my component:
const component = (
<Provider store={store}>
<ConnectedRouter history={createBrowserHistory()}>
{routes()}
</ConnectedRouter>
</Provider>
);
Then, I call it like this:
render(component);
Do I need extra configuration on the ConnectedRouter or maybe I'm not building properly the routes and/or store?

Related

Implement Window Data Layer Push in React App

I'm trying to implement window.data.layer.push in my react application so I can use it with Google Tag Manager but I am unsure where it would go. this is my base app.js file
// import the GTM Module so you can access it
import TagManager from "react-gtm-module";
const tagManagerArgs = {
gtmId: "GTM-P8J3MKF"
};
TagManager.initialize(tagManagerArgs)
const { persistor, store } = configureStore();
const MGMW = () => (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
{/*<LoginScene className='main-background' />*/}
<LayoutBase />
<GlobalModals />
</PersistGate>
</Provider>
);
const rootElement = document.getElementById('app-root');
if (rootElement) render(<MGMW />, rootElement);
export default MGMW;
You must use useEffect hook.
useEffect(() => {
/*script to be executed here*/
}, [])
This is the componentDidMount version of React Hooks. More on the subject here: https://reactjs.org/docs/hooks-effect.html

Invariant Violation: Element type is invalid: expected a string or a class but got: undefined. Check the render method of `MyApp`

I'm trying to load a static HTML from the meteor server side that also uses redux and router. However, every time I try to render my component with renderToString() I get the error indicated in the title. What am I doing wrong?
I've already tried using React.renderComponentToString as a possible alternative, but I get the error that React.renderComponentToString is not a function. How else am I going to pass an argument?
import React from 'react';
import {onPageLoad} from 'meteor/server-render';
import {StaticRouter} from 'react-router';
import {Provider} from 'react-redux';
import {createStore, applyMiddleware} from 'redux';
import {Helmet} from 'react-helmet';
import rootReducer, {initialState} from '../redux/reducers';
import HomePage from '../ui/homepage/HomePage';
export default renderServerPage = onPageLoad(sink => {
const context = {};
const store = createStore(rootReducer, initialState, applyMiddleware(thunk));
const MyApp = props => {
return (
<Provider store={store}>
<StaticRouter location={sink.request.url} context={context}>
<Route path="/" component={HomePage}/>
</StaticRouter>
</Provider>
);
}
// The following line is causing the error
sink.renderIntoElementById('app', renderToString(<MyApp />));
const helmet = Helmet.renderStatic();
sink.appendToHead(helmet.title.toString(
"Afterschools, Enrichment Programs, Growth, & Experiences - Fun2Bright"
));
sink.appendToBody(
<script>
window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState).replace(/</g, '\\u003c')}
</script>
);
});
My other attempts include the following:
1) creating a component outside of the scope within the same file and passing store and sink.request.url as props
function MyApp (props) {
const context = {};
return (
<Provider store={props.store}>
<StaticRouter location={props.location} context={context}>
<Route path="/" component={HomePage}/>
</StaticRouter>
</Provider>
);
}
2) basically creating the same component but in another file and importing the component.
3) directly putting the element inside the renderToString:
sink.renderIntoElementById('app', renderToString(
<Provider store={store}>
<StaticRouter location={sink.request.url} context={context}>
<Route path="/" component={HomePage}/>
</StaticRouter>
</Provider>
));
4) using React.createElement without passing any props:
sink.renderIntoElementById('app', renderToString(React.createElement(MyApp)));
5) commenting out the following just to see if it's caused by any of my other imported components
<Route path="/" component={HomePage}/>
I finally figured the issue. It turns out that simply using react-router doesn't allow me to use DOM-aware components like and , so I needed to use react-router-dom instead. react-router-dom also re-exports all of react-router's exports, so I'll only ever need to use react-router-dom. I changed everything to be imported from 'react-router-dom':
import {Route, StaticRouter} from 'react-router-dom';
...
// inside onPageLoad
const App = props => {
return (
<Provider store={store}>
<StaticRouter location={props.location} context={context}>
<Route path="/" component={HomePage}/>
</StaticRouter>
</Provider>
);
}
sink.renderIntoElementById('app', renderToString(<App store={store} location={sink.request.url}/>));
I found this from here: https://github.com/ReactTraining/react-router/issues/4648

How to get resultsState of react-instantsearch correctly with server-side render and integration with redux store

I try to get resultsState by call react-instantsearch's findResultsState API, But can't integrate with the component already connected with redux store. Error will show like below.
Invariant Violation: Could not find "store" in either the context or props of component . Either wrap the root component in a <Provider>, or explicitly pass "store" as a prop to component
Call api like this
findResultsState(
component: Search, {
searchState
});
My component looks like this. It is composed with some HOCs, and some HOC will connect with redux store through react-redux connect function.
Search = compose(
intlWrapper,
withModal,
withGlobalAlert,
withMainLayout,
injectIntl,
)(Search);
Server-side Provider will render like this
const appString = renderToString(
<Provider store={store}>
<StaticRouter location={req.url} context={ context }>
<Main />
</StaticRouter>
</Provider>
);
Client-side:
const store = configureStore(history,
window.__APP_INITIAL_REDUX_STATE__);
// Render component
hydrate(
<Provider store={store}>
<ConnectedRouter history={history}>
<Main />
</ConnectedRouter>
</Provider>,
document.getElementById('root'),
);
Main
<Switch>
{ routes.map( route => <Route key={ route.path } { ...route } />)}
</Switch>
routes
export default [
{
path: '/search',
component: Search,
},{
...
}
...
];

In react router v4 why does BrowserRouter work only inside the main render function?

For some reason I can't find a way to import the whole router as a component into the main render function that appends it to the body.
When I do this, all works fine:
render(
<Provider store={store}>
<Router history={history}>
<AppProvider store={store}/> // Containing the routing
</Router>
</Provider>,
document.getElementById('root')
)
But when I move everything into AppProvider like this
render(
<AppProvider store={store} history={history}/>,
document.getElementById('root')
)
AppProvider:
class AppProvider extends Component {
constructor (props) {
super(props)
this.state = {...}
}
render () {
return (
<Provider store={this.props.store}>
<Router history={this.props.history}>
/* ROUTES */
</Router>
</Provider>
)
}
}
export default withRouter(connect(mapStateToProps, {})(AppProvider))
I get
Uncaught TypeError: Cannot read property 'route' of undefined
Any ideas why?

Redux-react connect function does not work for root component

I am using a middleware to restore Redux store from indexeddb. I want to use that data in the root component for routing, to check if user is connected. But it seems that the connect function does not connect the root component state to Redux.
When I was debugging I saw mapStateToProps never actually runs. This is the relevant part of index.js:
class AppProvider extends Component {
constructor (props) {
super(props)
this.state = {}
}
componentWillMount () {
persistStore(store, {storage: localforage}) // Populates the store from indexedDB
}
render () {
return (
<Provider store={store}>
<Router history={history}> // Here I need the user from redux
<Route path="/login" render={() => (
this.state.user ? ( <Redirect to="/dashboard"/> ) : ( <LoginPage/> )
)}/>
</Router>
</Provider>
)
}
}
function mapStateToProps (state, ownProps) {
return {
user: state.user // function never runs!
}
}
withRouter(connect(mapStateToProps, {})(AppProvider))
render(
<AppProvider/>,
document.getElementById('root')
)
UPDATE:
When trying this:
const Root = withRouter(connect(mapStateToProps, {})(AppProvider))
render(
<Root/>,
document.getElementById('root')
)
I get
Uncaught TypeError: Cannot read property 'route' of undefined
You're not using the connected component.
Neither withRouter nor connect modify the original component. They simply return a new component.
Try this;
const AppProviderWithRedux = withRouter(connect(mapStateToProps, {})(AppProvider))
render(
<AppProviderWithRedux/>,
document.getElementById('root')
)

Categories

Resources