New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
reducer not updating component... #55
Labels
Comments
/// <reference path="../../../../../../typings/tsd.d.ts" />
import * as lodash from 'lodash';
import {
SEND_REQUEST,
RECEIVE_RESPONSE,
IFormMapping
} from '../actions';
const initState: any = {
success: false,
hasError: {
name: ''
},
help: {
name: ''
},
loading: false,
errormessage: ''
};
export function formSignup(state: any = initState, action: IFormMapping): any {
let delta: Object;
switch (action.type) {
case SEND_REQUEST:
delta = lodash.assign({}, state, {
name: action.name,
username: action.username,
password: action.password,
email: action.email
});
return delta;
case RECEIVE_RESPONSE:
delta = lodash.assign({}, state, {
success: action.success,
errormessage: action.errormessage,
hasError: action.hasError,
help: action.help,
loading: action.loading
});
return delta;
default:
return state;
}
} |
/// <reference path="../../../../../../typings/tsd.d.ts" />
import Fetch from '../../../api/jsonfetch';
import ParseValidation, { IValidation } from '../../../api/parsevalidation';
// import fetch from 'isomorphic-fetch';
export const FORM_INIT: string = 'FORM_INIT';
export const SEND_REQUEST: string = 'SEND_REQUEST';
export const RECEIVE_RESPONSE: string = 'RECEIVE_RESPONSE';
/* **************** Form Send Action Interface ****************** */
// start(callback: (startStatus: bool, engineType: string) => void) : void;
// http://stackoverflow.com/questions/17865620/typescript-multiple-inheritance-workarounds
export interface IFormAbstract {
type: string;
}
export interface IFormRequest extends IFormAbstract {
name: string;
username: string;
password: string;
email: string;
}
export interface IFormResponse extends IFormAbstract {
success: boolean;
errormessage: string;
hasError: any;
help: any;
loading: boolean;
}
export interface IFormMapping extends IFormRequest, IFormResponse {
// success?: boolean;
// error?: boolean;
// hasError?: any;
// help?: any;
// loading?: boolean;
// name?: string;
// username?: string;
// password?: string;
// email?: string;
}
/* **************** Form Send Action Event ********************** */
export function onFormInit(): IFormAbstract {
return {
type: FORM_INIT
};
}
/* **************** Form Send Action Event ********************** */
export function onSendFormAction(name: string, username: string, password: string, email: string): IFormRequest {
return {
type: SEND_REQUEST,
name,
username,
password,
email
};
}
/* **************** Form Receive Action Event ********************** */
export function onReceiveFormAction(success: boolean, errormessage: string, hasError: any, help: any, loading: boolean): IFormResponse {
return {
type: RECEIVE_RESPONSE,
success: success,
errormessage: errormessage,
hasError: hasError,
help: help,
loading: loading
};
}
// TODO Interface for Data
export function handleRequest(data: any): any {
return (dispatch: any, getState: any) => {
dispatch(onSendFormAction(data.name, data.username, data.password, data.email));
let request: any = {
method: 'POST',
url: '/api/signup',
data: data
};
Fetch(request, (err: any, response: any) => {
if (!err) {
window.location.href = '/account';
response.success = true;
}
let validation: IValidation = ParseValidation(response.validation, response.message);
dispatch(onReceiveFormAction(response.success, validation.error, validation.hasError, validation.help, response.loading));
});
};
} |
/// <reference path='../../../../../../../typings/tsd.d.ts' />
// Core Imports
import * as React from 'react';
import { connect } from 'react-redux';
// Styles
import './_Form.scss';
// Page Components
import { ControlGroup } from './components/ControlGroup/ControlGroup';
import { TextControl } from './components/TextControl/TextControl';
import { Button } from './components/Button/Button';
import { Spinner } from './components/Spinner/Spinner';
// Behaviors and Actions
import {
// SEND_REQUEST,
// RECEIVE_RESPONSE,
IFormMapping,
// onFormAction,
// handleRequest,
onFormInit,
onReceiveFormAction
} from '../../actions';
// Interfaces
interface IFormProps {
dispatch?: (func: any) => void;
store?: any;
}
interface IFormState {
success?: boolean;
errormessage?: string;
hasError?: any;
help?: any;
loading?: boolean;
name?: string;
username?: string;
password?: string;
email?: string;
}
// Decorators
function select(state: { formSignup: IFormMapping; }): IFormState {
const { formSignup }: { formSignup: IFormMapping; } = state;
const {
errormessage,
name,
username,
password,
email,
success,
hasError,
help,
loading
}: IFormMapping = formSignup;
console.warn('select() :: errormessage');
console.warn(errormessage);
return {
errormessage,
name,
username,
password,
email,
success,
hasError,
help,
loading
};
}
@connect(select)
export class Form extends React.Component<IFormProps, IFormState> {
public constructor(props: any = {}) {
super(props);
console.warn('constructor()');
this.state = {
success: false,
hasError: {
name: ''
},
help: {
name: ''
},
loading: false,
errormessage: 'init'
};
}
public componentDidMount(): void {
// this.refs.nameControl.refs.inputField.getDOMNode().focus();
console.warn('componentDidMount()');
const { dispatch }: IFormProps = this.props;
dispatch(
onFormInit()
);
}
public onSubmit(event: any): void {
event.preventDefault();
event.stopPropagation();
const { dispatch }: IFormProps = this.props;
/*
dispatch(
handleRequest({
name: this.state.name,
username: this.state.username,
password: this.state.password,
email: this.state.email
})
);
*/
dispatch(
onReceiveFormAction(false, 'ERROR', {}, {}, false)
);
}
public linkState(value: string): any {
return {
value: this.state[value],
requestChange: function(newValue: string): void {
this.state[value] = newValue;
}
};
}
public render(): React.ReactElement<{}> {
let alerts: any[] = [];
console.warn('render()');
console.warn('this.state.errormessage');
console.warn(this.state.errormessage);
if (this.state.success) {
alerts.push(<div key='success' className='alert alert-success'>
Success.Redirecting...
</div>);
}
if (this.state.errormessage !== '') {
alerts.push(<div key='danger' className='alert alert-danger'>
{this.state.errormessage}
</div>);
}
let formElements: React.ReactElement<{}>;
if (!this.state.success) {
formElements = <fieldset>
<TextControl
name='name'
label='Name'
ref='nameControl'
hasError={this.state.hasError.name}
valueLink={this.linkState('name') }
help={this.state.help.name}
disabled={this.state.loading}
/>
<TextControl
name='email'
label='Email'
hasError={this.state.hasError.email}
valueLink={this.linkState('email') }
help={this.state.help.email}
disabled={this.state.loading}
/>
<TextControl
name='username'
label='Username'
hasError={this.state.hasError.username}
valueLink={this.linkState('username') }
help={this.state.help.username}
disabled={this.state.loading}
/>
<TextControl
name='password'
label='Password'
type='password'
hasError={this.state.hasError.password}
valueLink={this.linkState('password') }
help={this.state.help.password}
disabled={this.state.loading}
/>
<ControlGroup hideLabel={true} hideHelp={true}>
<Button
type='submit'
inputClasses={{ 'btn-primary': true }}
disabled={this.state.loading}>
Create my account
<Spinner space='left' show={this.state.loading} />
</Button>
</ControlGroup>
</fieldset>;
}
return (
<section>
<h1 className='page-header'>Sign up</h1>
<form onSubmit={(e: any) => this.onSubmit(e) }>
{alerts}
{formElements}
</form>
</section>
);
}
} |
Turns out it's true, state defaults come from reducer defaults in arguments. /// <reference path="../../../../../../typings/tsd.d.ts" />
import * as lodash from 'lodash';
import {
FORM_UPDATE,
SEND_REQUEST,
RECEIVE_RESPONSE,
IFormMapping
} from '../actions';
export function formSignup(
state: any = {
name: '',
username: '',
password: '',
email: '',
success: false,
hasError: {
},
help: {
},
loading: false,
errormessage: '',
field: '',
value: ''
},
action: IFormMapping
): any {
let delta: Object;
switch (action.type) {
case FORM_UPDATE:
let obj: any = {};
obj[action.field] = action.value;
delta = lodash.assign({}, state, obj);
return delta;
case SEND_REQUEST:
delta = lodash.assign({}, state, {
name: action.name,
username: action.username,
password: action.password,
email: action.email
});
return delta;
case RECEIVE_RESPONSE:
delta = lodash.assign({}, state, {
success: action.success,
errormessage: action.errormessage,
hasError: action.hasError,
help: action.help,
loading: action.loading
});
return delta;
default:
return state;
}
} And don't use state, that's the whole point of the connect() decorator is to map that to props. /// <reference path='../../../../../../../typings/tsd.d.ts' />
// Core Imports
import * as React from 'react';
import { connect } from 'react-redux';
// Styles
import './_Form.scss';
// Page Components
import { ControlGroup } from './components/ControlGroup/ControlGroup';
import { TextControl } from './components/TextControl/TextControl';
import { Button } from './components/Button/Button';
import { Spinner } from './components/Spinner/Spinner';
// Behaviors and Actions
import {
// SEND_REQUEST,
// RECEIVE_RESPONSE,
IFormMapping,
// onFormAction,
onFormUpdate,
handleRequest,
onFormInit,
// onReceiveFormAction
} from '../../actions';
// Interfaces
interface IFormProps {
dispatch?: (func: any) => void;
store?: any;
name?: string;
username?: string;
password?: string;
email?: string;
}
interface IFormState {
success?: boolean;
errormessage?: string;
hasError?: any;
help?: any;
loading?: boolean;
name?: string;
username?: string;
password?: string;
email?: string;
field?: string;
value?: string;
}
// Decorators
function select(state: { formSignup: IFormMapping; }): IFormState {
const { formSignup }: { formSignup: IFormMapping; } = state;
const {
errormessage,
name,
username,
password,
email,
success,
hasError,
help,
loading,
field,
value
}: IFormMapping = formSignup;
return {
errormessage,
name,
username,
password,
email,
success,
hasError,
help,
loading,
field,
value
};
}
@connect(select)
export class Form extends React.Component<IFormProps, IFormState> {
public constructor(props: any = {}) {
super(props);
}
public componentDidMount(): void {
// this.refs.nameControl.refs.inputField.getDOMNode().focus();
const { dispatch }: IFormProps = this.props;
dispatch(
onFormInit()
);
}
public handleChange(event: any): void {
const { dispatch }: IFormProps = this.props;
dispatch(
onFormUpdate(event.target.name, event.target.value)
);
}
public onSubmit(event: any): void {
event.preventDefault();
event.stopPropagation();
const {
dispatch,
name,
username,
password,
email
}: IFormProps = this.props;
dispatch(
handleRequest({
name,
username,
password,
email
})
);
}
public render(): React.ReactElement<{}> {
let alerts: any[] = [];
const {
errormessage,
name,
username,
password,
email,
success,
hasError,
help,
loading
}: IFormState = this.props;
if (success) {
alerts.push(<div key='success' className='alert alert-success'>
Success.Redirecting...
</div>);
}
if (errormessage !== '') {
alerts.push(<div key='danger' className='alert alert-danger'>
{errormessage}
</div>);
}
let formElements: React.ReactElement<{}>;
if (!success) {
formElements = <fieldset>
<TextControl
name='name'
label='Name'
ref='nameControl'
hasError={hasError.name}
value={name}
onChange={ (e: any) => this.handleChange(e) }
help={help.name}
disabled={loading}
/>
<TextControl
name='email'
label='Email'
hasError={hasError.email}
value={email}
onChange={ (e: any) => this.handleChange(e) }
help={help.email}
disabled={loading}
/>
<TextControl
name='username'
label='Username'
hasError={hasError.username}
value={username}
onChange={ (e: any) => this.handleChange(e) }
help={help.username}
disabled={loading}
/>
<TextControl
name='password'
label='Password'
type='password'
hasError={hasError.password}
value={password}
onChange={ (e: any) => this.handleChange(e) }
help={help.password}
disabled={loading}
/>
<ControlGroup hideLabel={true} hideHelp={true}>
<Button
type='submit'
inputClasses={{ 'btn-primary': true }}
disabled={loading}>
Create my account
<Spinner space='left' show={loading} />
</Button>
</ControlGroup>
</fieldset>;
}
return (
<section>
<h1 className='page-header'>Sign up</h1>
<form onSubmit={(e: any) => this.onSubmit(e) }>
{alerts}
{formElements}
</form>
</section>
);
}
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Pretty sure I'm not mutating it, unless you consider setting default state props? meh
reduxjs/redux#153
reduxjs/redux#585
The text was updated successfully, but these errors were encountered: