loading module inside redux connect - reactjs

I'm trying to figure out what I did wrong, here's the scenario
Greeting.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import name from './name';
class SayGreeting extends Component {
componentDidMount() {
console.log(name);
}
render() {
return (
<div>
Good Morning to you, {name}
</div>
)
}
}
const mapStateToProps = ...
const mapDispatchToProps = ...
const Greeter = connect(
mapStateToProps,
mapDispatchToProps
)(SayGreeting)
export default Greeter;
name.js
import React from 'react';
const Name = () => (<div>Yoshie</div>);
export default Name;
when I log out "name", it logs out a connect function instead of the jsx that I expected:
function Connect(props, context) {
_classCallCheck(this, Connect);
var _this = _possibleConstructorReturn(this, _Component.call(this, props, context));
_this.version = versio…
I wonder if I did anything wrong... thanks for the help!

have you try it like this,
EDIT: try import the name inside curly braces
import {Name} from './name'
class SayGreeting extends Component {
componentDidMount() {
console.log(name);
}
render() {
return (
<div>
Good Morning to you, <Name/>
</div>
)
}
}

Related

Embedded Child Component in React is Undefined

I have the following parent component:
import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux';
import {bindActionCreators} from 'redux';
import _ from "lodash";
import ChildComponent from "./ChildComponent";
class ParentComponent extends Component {
constructor(props) {
super(props);
this.state = {
};
}
render() {
return (
<div>
I'm at Parent
<ChildComponent/>
</div>
);
}
}
function mapStateToProps(state) {
return { }
}
export default connect(mapStateToProps, null)(ParentComponent);
Inside the parent has a component called ChildComponent that looks like this:
import React, { Component, PropTypes } from "react";
import { connect } from "react-redux";
import { reduxForm } from "redux-form";
import { bindActionCreators } from "redux";
class ChildComponent extends Component {
constructor(props) {
super(props);
}
componentWillMount() {
}
render() {
return (
<div>
at the child
</div>
);
}
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(
{
},
dispatch
);
}
function mapStateToProps(state) {
return {
};
}
export default connect(mapStateToProps, mapDispatchToProps)(
ChildComponent
);
When I try adding the child component I keep getting this error:
But if I click continue the page turns back to normal. I don't understand how the child component is undefined. It's just embedded and does not include any props.
UPDATE:
I'm not getting the error anymore but I notice my page turns blank when I open this particular component. I'll be doing a bit more troubleshooting.
I tried out your code, and it works fine for me. My thought was maybe what your entry file looks like? or file structure? If you like you can try the following syntax for the parent and child - it worked this way as well:
Child:
const mapStateToProps = () => {
return {}
}
const ConnectedChildComponent = connect(
mapStateToProps,
{})(ChildComponent)
export default ConnectedChildComponent;
Parent:
const mapStateToProps = () => {
return {}
}
const ConnectedParentComponent = connect(
mapStateToProps,
{})(ParentComponent)
export default ConnectedParentComponent;
In your ParentComponent change:
import ChildComponent from "./ChildComponent";
to
import ChildComponent from "./ChildComponent.jsx";
i.e. add the missing ".jsx" extension. Your code is most likely determining the import to be a ".js" file by default, whereas it's actually a ".jsx" file.

cant access to store in redux app

i want to use redux in my react native app
and i make my reducer correctly (i think ) and after that create store and then use dispatch or store but i get error actually i cant use dispatch
my app.js:
const store = createStore(rootReducer, applyMiddleware(logger));
export default class taav extends Component {
render() {
return (
<Provider store={store}>
<Chatroom />
</Provider>
);
}
}
and my chatroom :
import React, {Component} from 'react';
import {Text, Button, TabBarIOS, View} from 'react-native'
import MessageList from './messageList'
import {connect} from 'react-redux'
const mapStateToProps = (state) => {
return {
testtest: state.chatroom.teststore.test
}
}
export const Testredux = connect(mapStateToProps)(MessageList)
export default class Chatroom extends Component {
state = {
test2: "dfsd"
}
componentDidMount() {
console.log('this')
}
btn() {
dispatch({type: 'test1'})////////////this is wrong???
}
render() {
return (
<View>
<Testredux test={'sdfdsf'}/>
<Button title={'sdfsdf'} onPress={this.btn.bind(this)}/>
</View> )
}
}
do you know why i cant use dispatch????
You have not imported the 'dispatch' function anywhere so that's why you can't use it. You would have to import your store and then call store.dispatch().
However, the best (and recommended) way would be to use mapDispatchToProps with the connect function from react-redux when you export your Chatroom component:
function mapDispatchToProps(dispatch) {
return({
sendTestAction: () => { dispatch({type: 'test1'}) }
})
}
...and then use it with connect like this when you export your component:
connect(mapStateToProps, mapDispatchToProps)(Chatroom)
In your Chatroom component you can then do:
render() {
return (
<View>
<Testredux test={ 'sdfdsf' }/>
<Button title={ 'sdfsdf' } onPress={ this.props.sendTestAction }/>
</View>
)
}
I hope this helps.
You're connecting the wrong class
export const Testredux = connect(mapStateToProps)(MessageList)
should be
export const Testredux = connect(mapStateToProps)(Chatroom)
dispatch is a prop passed to the component wrapped in the connect call. Since you're wrapping MessageList instead of Chatroom, instances of Chatroom cannot access any props passed by Redux.
Additionally, dispatch should be accessed as a prop, so it should be this.props.dispatch instead of just dispatch:
btn() {
this.props.dispatch({type: 'test1'})
}

Redux error: mapDispatchToProps throws error

I am new to react-redux and I am having some difficulty in understanding the syntax. I am pasting my sample code below... please help me understand if there are any syntactical errors.
SampleParent.js:
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { fetchNames, fetchDownloadLink } from '../../actions/actions'
import SampleChild from '../ui/SampleChild'
class SampleParent extends Component {
constructor(props) {
super(props) ;
}
componentDidMount() {
const { dispatch } = this.props
dispatch(fetchNames());
}
render() {
return(<div><ul id="myUL">{this.props.reports.map((report) => (
<li>
<SampleChild
key={report.id}
label={report.label}
uri={() => fetchDownloadLink("http://localhost:8080/sample"+this.props.uri+".pdf")}
/>
</li>))}</ul></div>)}
}
function mapStateToProps(state) {
const { reports } = state
return {
reports
}
}
const mapDispatchToProps = dispatch => {
return {
fetchDownloadLink(url) {
dispatch(
fetchDownloadLink(url)
)
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(ReportsApp)
SampleChild.js
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { fetchDownloadLink } from '../../actions/actions'
class OpenReport extends Component {
constructor(props) {
super(props) ;
}
render(){
return(<div className="in_sample" id={this.props.label}>
{this.props.label}
<a href={this.props.uri}>
<img src="../images/pdf-file_128.png" height="25px" width="25px"></img></a><br></br></div>
)
}
}
module.exports = OpenReport;
Currently I am getting this error:
Uncaught TypeError: dispatch is not a function
at ReportsApp.componentDidMount (bundle.js:39883)
Basically what I need to do is get a url as a string from the 'fetchDownloadLink ' function and pass this string to my child component. Is there any other way to do that?
Please suggest...
Thanks in advance!
According to the Documentaion:
mapDispatchToProps returns an object that somehow uses dispatch to bind
action creators in your own way.
However in your case you are returning an object without keys. Change your function to
const mapDispatchToProps = dispatch => {
return {
fetchDownloadLink: (url) => dispatch(fetchDownloadLink(url))
}
}
}
MoreOver, using connect function you need to connect mapStateToProps and mapDispatchToProps function to the component in which you will be using the action creators which in your case is SampleParent
Also if you pass mapDispatchToProps as the second parameter to connect, then dispatch is not available as a prop to your component.
So change your code to the following
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { fetchNames, fetchDownloadLink } from '../../actions/actions'
import SampleChild from '../ui/SampleChild'
class SampleParent extends Component {
constructor(props) {
super(props) ;
}
componentDidMount() {
const { dispatch } = this.props
this.props.fetchNames();
}
render() {
return(<div><ul id="myUL">{this.props.reports.map((report) => (
<li>
<SampleChild
key={report.id}
label={report.label}
uri={() => this.props.fetchDownloadLink("http://localhost:8080/sample"+this.props.uri+".pdf")}
/>
</li>))}</ul></div>)}
}
}
function mapStateToProps(state) {
const { reports } = state
return {
reports
}
}
const mapDispatchToProps = dispatch => {
return {
fetchDownloadLink: (url) => dispatch(fetchDownloadLink(url)),
fetchNames: () => dispatch(fetchNames)
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(SampleParent)
The problem is that you are passing your action creator as a prop uri to your child component, and then using that prop as an HREF tag.
You should instead pass it as onChildClick (example name) prop to your report item component, and call it on the onClick prop of the <a>.
<a onClick={ this.props.onChildClick }>xxxx</a>
The previous answer about the action creator mapping is fine, but you don't even need a function: if you use an object with functions as keys, they will be wrapped with dispatch for you.
const mapDispatchToProps = {
fetchDownloadLink
}
EDIT after your updated question
I see the problem now. You don't have dispatch as prop because you're using mapDispatchToProps to provide some action creators as props. It doesn't make sense to map dispatch to fetchDownloadLink and not doing it as well for fetchNames. Map both or neither, but you shouldn't mix and match.

react-async-poll with a connected component

Looking at the docs for react-async-poll I'm following the Usage example to integrate asyncPoll into my component, but I'm getting a Uncaught TypeError: dispatch is not a function complaint from within my onPollinterval function
import React, { Component } from 'react';
import { connect } from 'react-redux';
import asyncPoll from 'react-async-poll';
import { fetchCaCities, } from '../actions';
import MyMap from './my-map';
class CaliforniaMap extends Component {
componentDidMount() {
this.props.fetchCaCities();
}
render() {
return (
<div>
<h1>California Map</h1>
<MyMap center={[37.5, -120]} zoom={6} layers={[this.props.caCities]} />
</div>
);
}
}
const onPollInterval = (props, dispatch) => {
console.log(dispatch); // undefined
return dispatch(fetchCaCities());
};
const mapStateToProps = state => ({
caCities: state.map.california.caCities,
});
export default asyncPoll(60 * 1000, onPollInterval)(connect(
mapStateToProps, { fetchCaCities }
)(CaliforniaMap)
Maybe react-async-poll doesn't work for connected components?
According to the docs:
The dispatch parameter is only passed to [onInterval] if it is
available in props, otherwise it will be undefined.
The example they give is confusing because it does not define dispatch anywhere, but they show onPollInterval using it.

Decoupling React Components and Redux Connect

As seen here I am trying to decouple my app's components as much as I can and make them not aware of any storage or action creator.
The goal is to have them to manage their own state and call functions to emit a change. I have been told that you do this using props.
Considering
// Menu.jsx
import React from 'react'
import { className } from './menu.scss'
import Search from 'components/search'
class Menu extends React.Component {
render () {
return (
<div className={className}>
<a href='#/'>Home</a>
<a href='#/foo'>foo</a>
<a href='#/bar'>bar</a>
<Search />
</div>
)
}
}
And
// Search.jsx
import React from 'react'
import { className } from './search.scss'
class Search extends React.Component {
render () {
let { searchTerm, onSearch } = this.props
return (
<div className={`search ${className}`}>
<p>{searchTerm}</p>
<input
type='search'
onChange={(e) => onSearch(e.target.value)}
value={searchTerm}
/>
</div>
)
}
}
Search.propTypes = {
searchTerm: React.PropTypes.string,
onSearch: React.PropTypes.function
}
export default Search
And reading here I see a smart use of Provider and connect and my implementation would look something like this:
import { bindActionCreators, connect } from 'redux'
import actions from 'actions'
function mapStateToProps (state) {
return {
searchTerm: state.searchTerm
}
}
function mapDispatchToProps (dispatch) {
return bindActionCreators({
dispatchSearchAction: actions.search
}, dispatch)
}
export default connect(mapStateToProps, mapDispatchToProps)(Search)
Assuming I have a store handling searchTerm as part of the global state.
Problem is, where does this code belongs to? If I put it in Search.jsx I will couple actions with the component and more important to redux.
Am I supposed to have two different versions of my component, one decoupled and one connect()ed and have <Menu /> to use it? If yes what would my files tree look like? One file per component or a like a make-all-connected.js ?
In redux, exist a new kind of component that is called containers, this is the component that use connect(mapStateToProps, mapActionsToProps), to pass the state and actions to the current component.
All depends of the use of the component. For example, if you component Search only going to be use with the same state and action, You container could be the same that your component like this:
// Search.jsx
import { connect } from 'redux'
import actions from 'actions'
import React from 'react'
import { className } from './search.scss'
class Search extends React.Component {
render () {
let { searchTerm, onSearch } = this.props
return (
<div className={`search ${className}`}>
<p>{searchTerm}</p>
<input
type='search'
onChange={(e) => onSearch(e.target.value)}
value={searchTerm}
/>
</div>
)
}
}
Search.propTypes = {
searchTerm: React.PropTypes.string,
onSearch: React.PropTypes.function
}
function mapStateToProps ({searchTerm}) {
return {
searchTerm
};
}
const mapDispatchToProps = {
onSearch: actions.search
}
export default connect(mapStateToProps, mapDispatchToProps)(Search)
But if your plan is reuse this component in another containers and the searchTerm or the action are different on the global state. The best way is passing this properties through other containers, and keep the Search component pure. Like this:
// Container1.jsx
import { connect } from 'redux'
import actions from 'actions'
import React, { Component } from 'react'
class Container1 extends Component {
render() {
const { searchTerm, handleOnSearch } = this.props;
return (
<div>
<Search searchTerm={searchTerm} onSearch={handleOnSearch} />
</div>
)
}
}
function mapStateToProps ({interState: {searchTerm}}) {
return {
searchTerm
};
}
const mapDispatchToProps = {
handleOnSearch: actions.search
}
export default connect(mapStateToProps, mapDispatchToProps)(Container1)
// Container2.jsx
import { connect } from 'redux'
import otherActions from 'otheractions'
import React, { Component } from 'react'
class Container2 extends Component {
render() {
const { searchTerm, handleOnSearch } = this.props;
return (
<div>
<Search searchTerm={searchTerm} onSearch={handleOnSearch} />
</div>
)
}
}
function mapStateToProps ({otherState: {searchTerm}}) {
return {
searchTerm
};
}
const mapDispatchToProps = {
handleOnSearch: otherActions.search
}
export default connect(mapStateToProps, mapDispatchToProps)(Container2)
For more information, read the official docs about using redux with react.

Resources