Created
August 14, 2020 07:51
-
-
Save DonkovtsevArthur/5d84a4049903b4cb50640a9cd6ab69c1 to your computer and use it in GitHub Desktop.
Slomux
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="app" /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Slomux — упрощённая, сломанная реализация Flux. | |
// Перед вами небольшое приложение, написанное на React + Slomux. | |
// Это нерабочий секундомер с настройкой интервала обновления. | |
// Исправьте ошибки и потенциально проблемный код, почините приложение и прокомментируйте своё решение. | |
// При нажатии на "старт" должен запускаться секундомер и через заданный интервал времени увеличивать свое значение на значение интервала | |
// При нажатии на "стоп" секундомер должен останавливаться и сбрасывать свое значение | |
const createStore = (reducer, initialState) => { | |
let currentState = initialState | |
const listeners = [] | |
const getState = () => currentState | |
const dispatch = action => { | |
currentState = reducer(currentState, action) | |
listeners.forEach(listener => listener()) | |
} | |
const subscribe = listener => listeners.push(listener) | |
return { getState, dispatch, subscribe } | |
} | |
const connect = (mapStateToProps, mapDispatchToProps) => | |
Component => { | |
class WrappedComponent extends React.Component { | |
render() { | |
return ( | |
<Component | |
{...this.props} | |
{...mapStateToProps(this.context.store.getState(), this.props)} | |
{...mapDispatchToProps(this.context.store.dispatch, this.props)} | |
/> | |
) | |
} | |
componentDidUpdate() { | |
this.context.store.subscribe(this.handleChange) | |
} | |
handleChange = () => { | |
this.forceUpdate() | |
} | |
} | |
WrappedComponent.contextTypes = { | |
store: PropTypes.object, | |
} | |
return WrappedComponent | |
} | |
class Provider extends React.Component { | |
getChildContext() { | |
return { | |
store: this.props.store, | |
} | |
} | |
render() { | |
return React.Children.only(this.props.children) | |
} | |
} | |
Provider.childContextTypes = { | |
store: PropTypes.object, | |
} | |
// APP | |
// actions | |
const CHANGE_INTERVAL = 'CHANGE_INTERVAL' | |
// action creators | |
const changeInterval = value => ({ | |
type: CHANGE_INTERVAL, | |
payload: value, | |
}) | |
// reducers | |
const reducer = (state, action) => { | |
switch(action.type) { | |
case CHANGE_INTERVAL: | |
return state += action.payload | |
default: | |
return {} | |
} | |
} | |
// components | |
class IntervalComponent extends React.Component { | |
render() { | |
return ( | |
<div> | |
<span>Интервал обновления секундомера: {this.props.currentInterval} сек.</span> | |
<span> | |
<button onClick={() => this.props.changeInterval(-1)}>-</button> | |
<button onClick={() => this.props.changeInterval(1)}>+</button> | |
</span> | |
</div> | |
) | |
} | |
} | |
const Interval = connect(dispatch => ({ | |
changeInterval: value => dispatch(changeInterval(value)), | |
}), | |
state => ({ | |
currentInterval: state, | |
}))(IntervalComponent) | |
class TimerComponent extends React.Component { | |
state = { | |
currentTime: 0 | |
} | |
render() { | |
return ( | |
<div> | |
<Interval /> | |
<div> | |
Секундомер: {this.state.currentTime} сек. | |
</div> | |
<div> | |
<button onClick={this.handleStart}>Старт</button> | |
<button onClick={this.handleStop}>Стоп</button> | |
</div> | |
</div> | |
) | |
} | |
handleStart() { | |
setTimeout(() => this.setState({ | |
currentTime: this.state.currentTime + this.props.currentInterval, | |
}), this.props.currentInterval) | |
} | |
handleStop() { | |
this.setState({ currentTime: 0 }) | |
} | |
} | |
const Timer = connect(state => ({ | |
currentInterval: state, | |
}), () => {})(TimerComponent) | |
// init | |
ReactDOM.render( | |
<Provider store={createStore(reducer)}> | |
<Timer /> | |
</Provider>, | |
document.getElementById('app') | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.7.2/prop-types.min.js"></script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment