i am new to redux and i'm trying to dispatch an action from inside a function but it says "dispatch is not defined no-undef". Can anyone tell me what i'm doing wrong
import React, { Component } from 'react';
import {connect} from 'react-redux';
import {getYear} from '../actions/getYearAction';
import {requestYear} from '../actions';
class SigninForm extends Component {
constructor(props){
super(props);
this.state = {
car :{
year: '',
brand:[],
}
}
}
getYear(){
return this.props.year.map( (year, id) => {
return(
<option value={year} key={id}>{year}</option>
)
})
}
handleSelection(e){
dispatch(requestYear( e.target.value ));
}
render() {
return (
<div>
<form>
<select onChange = {this.handleSelection.bind(this)}>
<option value="" selected disabled hidden>--YEAR--</option>
{this.getYear()}
</select><br/>
<select>
<option value='' selected disabled>-Brand-</option>
</select>
<button type='submit'>Add</button>
{this.props.value}
</form>
</div>
);
}
}
function mapStateToProps(state){
return{
year: state.year
}
}
export default connect( mapStateToProps)(SigninForm);
i have to make an api call with the year selected from saga but i don't know how to do it.
here's my action
import { createAction } from 'redux-actions';
export const REQUEST_YEAR = 'REQUEST_YEAR';
export const requestYear = createAction(REQUEST_YEAR);
Please help me
Thank you
dispatch is a prop just like your other props, you need to call it with this.props.dispatch.
Also it's advisable to only pass in the actions that you want to call as props:
handleSelection(e) {
this.props.requestYear( e.target.value );
}
...
export default connect( mapStateToProps, { requestYear })(SigninForm);
Related
I basically making a todolist app.I just want the user entered text and add it to my state.But when i click the button the state is not getting updated with the new todoItem.please help with this.
My state is in Context.js
import React from 'react';
const Context=React.createContext();
const reducer=(state,action)=>{
switch(action.type){
case "ADD_TODO":
return {
...state,
todos:[action.payload,...state.todos]
}
default:
return state;
}
}
export class Provider extends React.Component{
state={
todos:[
{id:"1",todoItem:"Code daily"},
{id:"2",todoItem:"play"},
{id: '16a1c935-a033-4272-85b4-4412de42b59f', todoItem: 'wdwdwd'},
],
dispatch:action=>{
this.setState(state=>{
reducer(state,action)
})
}
}
render(){
return(
<Context.Provider value={this.state}>
{this.props.children}
</Context.Provider>
)
}
}
export const Consumer=Context.Consumer;
My Input Component for taking the todoitem input from user and add it to the state.But my page is reloading but my user entered text is not added to the state.And there is no error showing.
InputTodo.js
import React, { Component } from 'react';
import '../css/InputTodo.css';
import { v4 as uuidv4 } from 'uuid';
import {Consumer} from '../context';
class InputTodo extends Component {
constructor(props){
super(props);
this.state={
inputValue:""
};
}
OnChange(event){
const txtEntered=event.target.value;
this.setState({
inputValue:txtEntered,
});
}
handleButtonClicked=(dispatch,event)=> {
event.preventDefault();
const inputValue=this.state.inputValue;
const newTodo={
id:uuidv4(),
todoItem:inputValue,
}
dispatch({type:'ADD_TODO',payload:newTodo});
this.setState({
inputValue:"",
});
this.props.history.push('/');
}
render() {
return(
<Consumer>
{value=>{
const {dispatch}=value;
return (
<form onSubmit={this.handleButtonClicked.bind(this,dispatch)}>
<div className="form-group">
<input value={this.state.inputValue} onChange={this.OnChange.bind(this)} className="form-control" placeholder="Enter the todo" />
<button type="submit" className="btn btn-primary">Add</button>
</div>
</form>
)}}
</Consumer>
)
}
}
export default InputTodo;
You just forgot to return the new state in dispatch setState:
export class Provider extends React.Component{
state={
/* ... */
dispatch:action=>{
this.setState(state=>{
return reducer(state,action) /* <--- Here you missed the return */
})
}
}
/* ... */
I have this code:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { fetchWeather } from '../actions/index';
class SearchBar extends Component {
constructor(props) {
super(props);
this.state = { term: '' };
this.onInputChange = this.onInputChange.bind(this);
this.onFormSubmit = this.onFormSubmit.bind(this);
}
onInputChange(event) {
this.setState({ term: event.target.value });
}
onFormSubmit(event) {
event.preventDefault();
this.props.fetchWeather(this.state.term);
this.setState({ term: '' });
}
render() {
return (
<form onSubmit={this.onFormSubmit} className="input-group">
<input
placeholder="Get a five-day forecast in your favorite cities"
className="form-control"
value={this.state.term}
onChange={this.onInputChange}
/>
<span className='input-group-btn'>
<button type="submit" className="btn btn-secondary">
Submit
</button>
</span>
</form>
);
}
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({ fetchWeather }, dispatch)
}
export default connect(null, mapDispatchToProps)(SearchBar);
At one point in this tutorial, the author says that mapDispatchToProps hooks up our Action Creator fetchWeather to our component. But does it? Doesn’t it dispatch the action from our Action Creator to our reducers?
What is actually making this available in our component as props?
You can have
const mapDispatchToProps = { fetchWeather };
instead of
function mapDispatchToProps(dispatch) {
return bindActionCreators({ fetchWeather }, dispatch)
}
Anyway this is the block that makes your action creator available via this.props.
i create simple signin form for my website.
But i have a little problem.
When i type login and password and try send it to server i got error
Uncaught TypeError: this.props.signinUser is not a function
import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form';
import * as actions from '../../actions';
class Signin extends Component{
constructor(props){
super(props);
this.state= {};
this.onSubmit = this.onSubmit.bind(this);
}
renderField(field){
return(
<div className="form-group">
<label>{field.label}</label>
<input
className="form-control"
type="text"
{...field.input}
/>
</div>
);
}
onSubmit(e){
e.preventDefault();
let {login,password} = this.state;
//this.props.login(login,password);
console.log({login,password});
this.props.signinUser({login,password});
this.setState({
login: '',
password: ''
})
}
render(){
let {login,password} = this.state;
return(
<form onSubmit={this.onSubmit}>
<Field
label="Login:"
name="login"
component={this.renderField}
onChange={e => this.setState({login: e.target.value})}
/>
<Field
label="Password:"
name="password"
component={this.renderField}
onChange={e => this.setState({password: e.target.value})}
/>
<button action="submit" className="btn btn-primary"> Sign In </button>
</form>
);
}
}
function mapStateToProps(state) {
return { form: state.form };
}
export default reduxForm({
form: 'signin'
}, mapStateToProps, actions)(Signin);
And Actions.
import axios from 'axios';
export function signinUser({login,password}){
return function(dispatch){
axios.post('http://localhost:8080/auth', { login, password});
};
}
and finally reducer.
import { combineReducers } from 'redux';
import { reducer as fromReducer } from 'redux-form';
const rootReducer = combineReducers({
form: fromReducer
});
export default rootReducer;
I use react 16, react redux v5 and react-router v3, react form v7!
I think its problem with connect function from ReactForm!
The problem lies here
export default reduxForm({
form: 'signin'
}, mapStateToProps, actions)(Signin);
This should be
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
....
//remainder of the code
....
mapDispatchToProps =(dispatch)=>{
return {
actions : bindActionCreators(actions , dispatch)
};
}
Signin= connect(
mapStateToProps,
mapDispatchToProps
)(Signin);
export default reduxForm({
form: 'signin'
})(Signin);
You would need to change the call this.props.signinUser to this.props.actions.signinUser
More info at : https://redux-form.com/7.0.4/docs/faq/howtoconnect.md/
I am trying to dispatch a redux action when an element is clicked. Here is how I currently have things set up
the action
export function removeItem(idx) {
// remove the item at idx
return {
type: "DESTROY_ITEM",
payload: {idx: idx}
}
}
container component
import ItemUi from '../ui/Item';
import { connect } from 'react-redux'
import { removeItem } from '../../actions'
const mapDispatchToProps = dispatch => {
return({
destroyItem: (index) => {
dispatch(
removeItem(index)
)
}
})
}
export default connect(null, mapDispatchToProps)(ItemUi)
ui component
import React, { Component, PropTypes } from 'react';
class Item extends Component {
// ... methods removed for length
render() {
return (
<div>
<span
className="btn btn-primary btn-xs glyphicon glyphicon-trash"
onClick={() => {this.props.destroyItem(this.props.index)}}></span>
</div>
)
}
}
DestroyItem.propTypes = {
onRemoveItem: PropTypes.func
}
export default Item
the top level component
import React, { Component } from 'react';
import Item from './Item'
class App extends Component {
render() {
return(
<div className="container">
<NewItem/>
<ClearAll/>
<div className="panel-group" id="accordion">
{this.props.item.map(this.eachItem)} // <-- renders each item
</div>
</div>
)
}
}
export default App;
When the user clicks the span element shown in the Item ui component I want to fire the destroyItem action passing in the component's index prop. Instead I get the error
TypeError: _this2.props.destroyItem is not a function
Can you please provide some guidance on how I should do this? Let me know if there is any other useful context I can provide.
Try:
const mapDispatchToProps = {
destroyItem: removeItem
}
i don't know what im doing wrong.
I thought i got the point how to implement with redux.
My Problem is that the state of the Component is not propagating to the Component after the state changed. I know we have to create new state object and i'm sure im doing it right. But there is no changes.
And the other question is, why the state is in the object "resetLink" see image. Why is it not stored in the state Object?
Please help me to get it work.
Action for the redux:
export const sendResetLink = (email) => {
return {
type: RESET_LINK,
email
}
}
class App extends React.Component {
render() {
return <VisibleResetLink/>
}
}
This is where the magic with props and dispatch function happens:
import {connect} from 'react-redux';
import SendResetLink from '../components/SendResetLink.jsx';
import {sendResetLink} from '../actions/index'
import _ from 'lodash';
const mapDispatchToProps = (dispatch) => {
return {
onClick: (email) => {
dispatch(sendResetLink(email))
}
}
}
const mapStateToProps = (state) => {
console.log("actual state", state);
return _.assign({} , {state: state.resetLink});
}
const VisibleResetLink = connect(
mapStateToProps,
mapDispatchToProps
)(SendResetLink)
export default VisibleResetLink
This is the Component which load props but never rerender them when they change.
import React, { PropTypes } from 'react';
import ReactDOM from 'react-dom';
class SendResetLink extends React.Component {
constructor(props, email, result) {
super(props);
console.log('props',props);
this.onClick = props.onClick;
this.result = props.state.result;
this.input = props.state.email;
}
renderResult (result){
console.log("renderResult",result);
if(result)
return <div className="card-panel deep-orange lighten-4">Invalid username and password.</div>
}
render() {
return <div>
{this.renderResult(this.result)}
{this.result}
<form className="col s12" action="/login" method="post" onSubmit={e => {
e.preventDefault()
if (!this.input.value.trim()) {
return
}
this.onClick(this.input.value);
this.input.value = ''
} }>
<div className="row">
<div className="input-field col s12">
<i className="material-icons prefix">email</i>
<input id="email" type="email" name="email" className="validate" ref = {(node) => this.input = node } />
<label for="email">Email</label>
</div>
</div>
<div className="divider"></div>
<div className="row">
<div className="col m12">
<p className="right-align">
<button className="btn btn-large waves-effect waves-light" type="submit" name="action">Send reset key</button>
</p>
</div>
</div>
</form></div>
}
}
SendResetLink.propTypes = {
onClick: PropTypes.func.isRequired,
state: PropTypes.object.isRequired
}
export default SendResetLink
And this is the other relevant code snippet, where the reducer is implemented.
import _ from 'lodash';
const resetLink = (state = {email:"test#test.de", result:true}, action) => {
console.log('state', state)
switch (action.type) {
case 'RESET_LINK':
return _.assign({},state,{email: action.email, result: false});
default:
return state
}
}
export default resetLink;
import { combineReducers } from 'redux'
import resetLink from './ResetLinkReducer.jsx'
const resetApp = combineReducers({
resetLink
})
export default resetApp
import App from './components/app.jsx';
import {Provider} from 'react-redux';
import { createStore } from 'redux';
import { render } from 'react-dom';
import React from 'react';
import resetApp from './reducers/index.js';
let store = createStore(resetApp,{});
console.log(store)
render(<Provider store={store}>
<App />
</Provider>, document.getElementById('sendResetLinkComponent'));
console logs. After click the renderResult should change to false. But it stays on true
You set this.result in your SendResetLink component only once in the constructor, which is only executed when the component is instantiated. The constructor will not be executed every time the application's state changes:
this.result = props.state.result;
Instead of assigning this part of the state to an instance attribute of your react component, simply use the props attribute directly in your render() function:
{this.renderResult(this.props.state.result)}