Advanced React Component Patterns - 2
by,
Shakthishree
Simple Toggle Component
import React, {Component} from 'react';
import Switch from './switch';
export default class Toggle extends Component {
state = {on: false};
toggle = () => {
this.setState(({on}) => ({on: !on}));
this.props.onToggle(!this.state.on);
};
render() {
return (
<div>
<Switch
on={this.state.on}
onClick={this.toggle}
/>
<div>
{this.state.on ? 'on' : 'off'}
</div>
</div>
);
}
}
import React, {Component} from 'react';
import Toggle from './toggle';
export default class User extends Component {
onToggle = ( on ) => {
console.log( on ? 'On' : 'Off' );
};
render() {
return (
<Toggle onToggle = { this.onToggle } />
)
}
}
Flexible Toggle Component
Compound Component
export default class Toggle extends Component {
state = {on: false};
static On = ({on}) =>
(on ? <div>On</div> : null);
static Off = ({on}) =>
(on ? null : <div>Off</div>);
static Button = ({on, toggle}) =>
<Switch on={on} onClick={toggle} />;
toggle = () => {
this.setState(({on}) => ({on: !on}));
this.props.onToggle(!this.state.on);
};
render() {
return (
React.Children.map(
this.props.children, child =>
React.cloneElement(child, {
on: this.state.on,
toggle: this.toggle,
});
);
);
}
}
export default class User extends Component {
onToggle = on => {
console.log(on ? 'on' : 'false' );
};
render() {
return (
<Toggle onToggle={this.onToggle}>
<Toggle.Button />
<Toggle.Off />
<Toggle.On />
</Toggle>
);
}
}
React Context API
const ToggleContext = React.createContext();
static On = ({children}) =>
<ToggleContext.Consumer>
{({on, children}) => {
return on ? children : null;}}
</ToggleContext.Consumer>;
static Off = ({children}) =>
<ToggleContext.Consumer>
{({on, children}) => {
return on ? null : children;}}
</ToggleContext.Consumer>;
static Button = ({children}) =>
<ToggleContext.Consumer>
{({on, toggle}) =>
<Switch on={on} onClick={toggle} />}
</ToggleContext.Consumer>;
render() {
return (
<ToggleContext.Provider
value={{on: this.state.on,
toggle: this.toggle}}>
{this.props.children}
</ToggleContext.Provider>);}
export default class User extends Component {
onToggle = on => {
console.log(on ? 'on' : 'false' );
};
render() {
return (
<Toggle onToggle={this.onToggle}>
<div style={{
height: '40px',
width: '60px',
backgroundColor: '#7eb36d',
marginTop: '10px',
border: '1px solid grey',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}>
<Toggle.Button />
</div>
<Toggle.Off />
<Toggle.On />
</Toggle>
);
}
}
Render Props
import React, {Component} from 'react';
import Switch from './switch';
class Toggle extends Component {
state = {on: false};
toggle = () => {
this.setState({on: !this.state.on});
this.props.onToggle(this.state.on);
};
render(){
return(
this.props.children({
on: this.state.on,
toggle: this.toggle,
})
)
}
}
import React, {Component} from 'react';
import './switch';
export default class User extends Component {
onToggle = on => {
console.log(on ? 'on' : 'false' );
};
render() {
return (
<Toggle
onToggle={this.onToggle}
>
{({on, toggle, reset}) =>
<div>
{on ? 'on' : 'off'}
</div>
<Switch on={on} onClick={toggle} />
}
</Toggle>
);
}
}
State Initializers
import React, {Component} from 'react';
import Switch from './switch';
class Toggle extends Component {
static defaultProps = {
initialOn: false,
}
initialState = {on: this.props.initialOn ?
this.props.initialOn :
this.props.defaultProps.initialOn};
state = this.initialState;
toggle = () => {
this.setState({on: !this.state.on});
this.props.onToggle(this.state.on)
};
render(){
return(
this.props.children({
on: this.state.on,
toggle: this.toggle
})
)
}
}
import React, {Component} from 'react';
import './switch';
export default class User extends Component {
onToggle = on => {
console.log(on ? 'on' : 'false' );
};
render() {
return (
<Toggle
initialOn= {true}
onToggle={this.onToggle}
>
{({on, toggle, reset}) =>
<div>
{on ? 'on' : 'off'}
</div>
<Switch on={on} onClick={toggle} />
}
</Toggle>
);
}
}
Use Case
State Reducers
this.state = {
fieldStatus: {
feild1{
pristine: true,
dirty: false,
valid: false,
invalid: true,
error: {}
}
},
formStatus: {
pristine: true,
dirty: false,
valid: false,
invalid: true,
submitted: false
}
};
toggleStateReducer = (state, changes) => {
// state = current state, changes = triggered changes
return modifiedState;
}
render() {
return (
<Validator
stateReducer={this.toggleStateReducer}
>
{(formValue) =>
<input
modal = 'email'
validation = 'email'
/>
<text>
{formValue.email.error.errorMessage}
</text>
<input
modal = 'password'
validation = 'isRequired'
/>
<text>
{formValue.password.error.errorMessage}
</text>
<button onClick={this.submit()}>
Submit </button>
<button onClick={this.reset()}>
Clear </button> }
</Validator>
HOC
function wrapper(Component, props) {
return (
<ToggleContext.Consumer {...props}>
{context => {
return <Component context={context} />;
}}
</ToggleContext.Consumer>
);
}
static On = ({children}) =>
wrapper(({on}) => (on ? children : null));
static Off = ({children}) =>
wrapper(({on}) => (on ? null : children));
static Button = ({children}) =>
wrapper(context => {
return <Switch
on={context.on}
onClick={context.context.toggle} />;
});
render() {
return (
<ToggleContext.Provider
value={{on: this.state.on,
toggle: this.toggle}}
{...this.props}
/>
);
render() {
return (
<Toggle onToggle={this.onToggle}>
<Toggle.Button />
<Toggle.Off>
<div>The button is off</div>
</Toggle.Off>
<Toggle.On>
<div>The button is on</div>
</Toggle.On>
</Toggle>
)
}
const ToggleContext = React.createContext();
static On = ({children}) =>
<ToggleContext.Consumer>
{({on, children}) => {
return on ? children : null;}}
</ToggleContext.Consumer>;
static Off = ({children}) =>
<ToggleContext.Consumer>
{({on, children}) => {
return on ? null : children;}}
</ToggleContext.Consumer>;
static Button = ({children}) =>
<ToggleContext.Consumer>
{({on, toggle}) =>
<Switch on={on} onClick={toggle} />}
</ToggleContext.Consumer>;
render() {
return (
<ToggleContext.Provider
value={{on: this.state.on,
toggle: this.toggle}}>
{this.props.children}
</ToggleContext.Provider>);}
HOC to handle state
import React,{Component, Fragment} from 'react';
import Toggle from './toggle';
class User extends Component{
render() {
return(
<Fragment>
<div>
{this.props.state.on ? 'On' : 'Off' }
</div>
<Switch
onReset={this.onReset}
on={this.props.state.on}
onClick={this.props.toggle}
/>
</Fragment>);
}
}
export default Toggle(User)
import React, {Component} from 'react';
function ToggleHOC ( Comp ){
return class Toggle extends Component {
state = {on: false};
toggle = () => {
this.setState({on: !this.state.on});
};
render() {
return <Comp {...this.props}
state={this.state}
toggle={this.toggle} />;
}
};
};
export default ToggleHOC;
Advanced react component patterns-2
By shakthishree
Advanced react component patterns-2
- 366