I am receiving the following error when trying to use the connect() function from react-redux:
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
Check the render method of `App`.
This is App:
import { Provider } from 'react-redux';
import configureStore from './store';
const App = class extends React.PureComponent {
render() {
const { title } = this.context;
return (
<div className="center-screen">
{title}
<Provider store={configureStore()}>
<Chat />
</Provider>
</div>
);
}
};
This is the relevent code end of chat:
import { connect } from 'react-redux';
...
const mapStateToProps = state => ({
...state
});
const mapDispatchToProps = dispatch => ({
addMessage: () => dispatch(addMessage)
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(Chat);
When using : "export default Chat" instead of connect, it's working fine..
Try this:
const ConnectedChat = connect(
mapStateToProps,
mapDispatchToProps
)(Chat);
export default ConnectedChat;
Or you may wish to rename the class definition to ConnectedChat and reverse the names so you can import it as just Chat.
Edit: Also make sure you're importing the Chat component in the App file, as well as the addMessage action creator if you're not.
Where are you defining Chat the component in your connect function?
My usual set up is (I'm using class but const ConnectedChart() would still be this same set up)
class ConnectedChart extends Component {
//// All code here render and return etc
}
const Chart = connect (mapStateToProps)(ConnectedChat);
export default Chart;
So that way you are essentially assigning a component to Chart with the connect statement and then you export default. I think exporting the connect statement directly might by throwing an error but if that doesn't work post the full chart component and I'll see if there is something else going on
EDIT: based on the full code
try this in your App.js:
import React from "react";
import ReactDOM from 'react-dom';
import "./App.css";
import ConnectedChat from "./Chat";
import { Provider } from "react-redux";
import configureStore from "./store";
ReactDOM.render(
<Provider store={configureStore()}>
<ConnectedChat />
</Provider>
);
and then put your div center screen in ConnectedChat
(if you are going to be adding more components later and want that div wrapping all of them, create a main app component like landing or something and call that between your provider instead of chat, and then in that landing component render the div and your ChatComponent)
Also if you don't have an index.js change the 'main' in your package.json to this App.js component
Related
I have a react component which I later render inside my index.js
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
App.jsx
import SomeComponent from "./Components/SomeComponent ";
function App() {
return <SomeComponent />
}
export default App;
SomeComponent.jsx (random name of component just for the example)
function SomeComponent() {
//some code
return ...
}
export default SomeComponent;
The problem is that I see a lot of people using
class SomeComponent extends React.Component {
componentDidMount()
//some code
render() {
return ...
}
}
And I want to use that "componentDidMount()" that I see in a lot of code examples, but in my way of doing things, it seems to don't be possible.
But... it is possible? or there is another similar method that can I use?
Thanks.
In the functional components, from React 16.8, we have React Hooks. And we can use useEffect() Hook to simulate what componentDidMount() does in a class based component. However, You will need to pass second argument as state value to the useEffect(), only then it behaves like componentDidMount() whenever the state value gets modified.
Something like this:
const [stateValue,useStateValue] = useState("enjoy");
useEffect(()=>{
// ... Your code
},[stateValue]);
My question is related to react-admin repo.
I want to dispatch an action, outside of scope of a component, in order to do that, I've read that I need to get access to the actual redux store itself, and dispatch on in directly,
so I know that the Admin component has an initialState prop, but it only accepts default state object, not the store. So I can't make a store and pass it in.
My question is:
How do I access redux store of an Admin component?
How can I dispatch an action outside of a component, when using Admin as my main app component?
my current app entry looks like this:
<AppLayoutDirection>
<Admin
title="My App"
locale="en"
dataProvider={dataProvider}
authProvider={authProvider}
i18nProvider={i18nProvider}
theme={themeProvider}
customSagas={customSagas}
appLayout={AppLayout}
>
{DynamicResource}
</Admin>
</AppLayoutDirection>
When you say that you need to dispatch an action outside the scope of a component, I suppose that it's in reaction to another action that was dispatched in the past.
In that case, that's what react-admin calls a side effect. React-admin handles side effects using redux-saga. Here is how to create a custom saga:
// in src/bitcoinSaga.js
import { put, takeEvery } from 'redux-saga/effects';
import { showNotification } from 'react-admin';
export default function* bitcoinSaga() {
yield takeEvery('BITCOIN_RATE_RECEIVED', function* () {
yield put(showNotification('Bitcoin rate updated'));
})
}
Register this saga in the <Admin> component as follows:
// in src/App.js
import React from 'react';
import { Admin } from 'react-admin';
import bitcoinSaga from './bitcoinSaga';
const App = () => (
<Admin customSagas={[ bitcoinSaga ]} dataProvider={simpleRestProvider('http://path.to.my.api')}>
...
</Admin>
);
export default App;
This is documented in the react-admin documentation, in the <Admin> chapter.
You could also simply use custom reducers if the computation is no async
// in src/App.js
import React from 'react';
import { Admin } from 'react-admin';
import reducers from './reducers';
const App = () => (
<Admin customReducers={customReducers} dataProvider={simpleRestProvider('http://path.to.my.api')}>
...
</Admin>
);
export default App;
I do not want to separate components when I am using react-navigation with redux.
How can I make a "const=" rather than make a new file and "export default"
const IntroScreen2 =connect(mapStateToProps,mapDispatchToProps)(IntroScreen2a)
const IntroScreen2 =()=> connect(mapStateToProps,mapDispatchToProps)(IntroScreen2a)
export default connect ...
which one is right?
https://codeshare.io/G79NRk
Do it something like this, define the component in the same file as where you use a default export of connect, passing in the component defined in the file.
These statements should help clear up your misunderstanding(s).
With react navigation, you have screens (components), and you have navigators. Navigators are created with screens (components).
You use react-redux's connect function to connect components to the redux store. You simply wrap a component in a call to connect, and export the return value of that, rather than the component itself.
When you create a navigator, you will need to import the components for your screens.
See the follow three pages, we make a component, export the component connected to the redux store, via react-redux's connect function.
Then we make a router, which exports a single stack navigator from react navigation, which defines a single screen, the component defined (mentioned above).
Then I have given an example of how you'd render that router, for example, inside your App.js.
some-component.js
import React, {Component} from "react";
import {connect} from "react-redux"
// Define the component
class SomeComponent extends Component {
render() {
return null;
}
}
// Map dispatch to props
const mapDispatchToProps = (dispatch) => {
return {};
}
// Map state to props
const mapStateToProps = (state) => {
return {};
};
// Export the component, passed into the connect function from react-redux.
export default connect (mapStateToProps, {}) (SomeComponent);
Then just import this file when defining your navigator with react navigation.
For example
router.js
import SomeComponent from "./some-component.js";
import {createStackNavigator} from "react-navigation";
export default createStackNavigator({
PageOne: {
screen: SomeComponent
}
});
In your App.js (root level)
import React, {Component} from "react";
import Router from "./router.js";
export default class App extends Component {
render () {
return <Router/>;
}
}
Something like that should get you sorted!
my selectors are executing before the component in which they are mapped are rendered. Why would this be? For example in the code below, the messages selector is executed before the Component renders. Thanks!
import React from 'react';
import {connect} from 'react-redux';
import * as selectors from './selectors';
const Component = ({message}) => (
<div>
{message}
</div>
);
const mapStateToProps = (state, props) => ({
message: selectors.message(state, props),
});
export default connect(mapStateToProps)(Component);
In React-Redux v5, the internal selector that implements mapState is initialized in the wrapper component constructor, and is called right away as part of that process.
In React-Redux v6, that internal selector is created in the wrapper component constructor, but called during the render process.
My React Native app has several conditions in which it needs to handle deep links when the user clicks on a link for an invite. My intent was to setup the Link listeners in the main app.js file and when a deep link is detected I need to pass the data into the Splash view to determine several factors before adding the user to the group they are invited to.
I am using React Navigation. I initially tried to use redux by updating the store with the url data but ran into timing issues as the Splash page was loading before redux was updated. So I have attempted to create an HOC wrapper for the Navigator as follows:
HOC Linker:
import * as React from "react";
const Linker = (Component) => {
return ({ children, ...props }) => {
return (
<Component { ...props }>
{ children }
</Component>
);
}
};
export default Linker;
In my App JS file I import the Linker and wrap the main navigator with the HOC component. I then add a prop that is updated when React Native Linking method detects a deep link. It updates state with the parameters.
App JS:
import Navigator from './ui/navigation/navigator';
const LinkerWrapper = Linker(Navigator);
render() {
return (
<LinkerWrapper linking={this.state.url} />
);
}
My Navigator file looks as follows:
Navigator:
import { createSwitchNavigator } from 'react-navigation';
import Splash from '../screens/splash/splash';
import AuthStack from './auth';
import AppStack from './app';
const Navigator = createSwitchNavigator({
Loading: Splash,
Auth: AuthStack,
App: AppStack
});
export default Navigator;
When I click on a deep link the app opens as expected, I parse the url and prep the data object, state is updated and the splash page is re rendered as expected, the props are passed through the HOC, but when the componentWillReceiveProps method is ran in the Splash page I do not see any props from the linking prop.
I have tried many different things. I am really new to react so I know I am probably doing something fundamentally wrong. I am guessing I am missing something with React Navigation. One of the things I tried was to change the screen value to a function passing in the props. I was hoping that would magically make the linking prop appear in the Splash page props. Below was my attempt:
import React from 'react';
import { createSwitchNavigator } from 'react-navigation';
import Splash from '../screens/splash/splash';
import AuthStack from './auth';
import AppStack from './app';
const Navigator = createSwitchNavigator({
Loading: {
screen: props => <Splash { ...props }/>
},
Auth: AuthStack,
App: AppStack
});
export default Navigator;
Unfortunately that didn't work. Any assistance would be appreciated.
Thanks.