javascript – 用redux创建秒表

前端之家收集整理的这篇文章主要介绍了javascript – 用redux创建秒表前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我一直在试图做一个反应和减速的秒表.弄清楚如何在redux中设计这样的东西,我一直很麻烦.

想到的第一件事就是采取了一项START_TIMER动作来设定初始补偿值.之后,我使用setInterval一次又一次地发出一个TICK动作,通过使用offset来计算已经过去了多少时间,将其添加到当前时间,然后更新偏移量.

这种方法似乎有效,但我不知道如何清除间隔来阻止它.此外,似乎这种设计很差,可能还有更好的办法.

这是一个完整的JSFiddle,具有START_TIMER功能工作.如果你现在只想看看我的reducer的样子,那就是:

  1. const initialState = {
  2. isOn: false,time: 0
  3. };
  4.  
  5. const timer = (state = initialState,action) => {
  6. switch (action.type) {
  7. case 'START_TIMER':
  8. return {
  9. ...state,isOn: true,offset: action.offset
  10. };
  11.  
  12. case 'STOP_TIMER':
  13. return {
  14. ...state,isOn: false
  15. };
  16.  
  17. case 'TICK':
  18. return {
  19. ...state,time: state.time + (action.time - state.offset),offset: action.time
  20. };
  21.  
  22. default:
  23. return state;
  24. }
  25. }

我真的很感激任何帮助.

解决方法

我可能建议使用不同的方式:仅存储计算商店中经过的时间所需的状态,并且让组件设置自己的间隔,但他们经常希望更新显示.

这样可以将动作调度保持在最小限度 – 只会启动和停止(并重置)定时器的动作.请记住,每次调度一个动作时,都会返回一个新的状态对象,然后每个连接的组件都会重新呈现(即使它们使用优化来避免包装组件中的重新渲染过多).此外,许多动作调度可能使得难以调试应用程序状态更改,因为您必须处理所有TICK以及其他操作.

以下是一个例子:

  1. // Action Creators
  2.  
  3. function startTimer(baseTime = 0) {
  4. return {
  5. type: "START_TIMER",baseTime: baseTime,now: new Date().getTime()
  6. };
  7. }
  8.  
  9. function stopTimer() {
  10. return {
  11. type: "STOP_TIMER",now: new Date().getTime()
  12. };
  13. }
  14.  
  15. function resetTimer() {
  16. return {
  17. type: "RESET_TIMER",now: new Date().getTime()
  18. }
  19. }
  20.  
  21.  
  22. // Reducer / Store
  23.  
  24. const initialState = {
  25. startedAt: undefined,stoppedAt: undefined,baseTime: undefined
  26. };
  27.  
  28. function reducer(state = initialState,action) {
  29. switch (action.type) {
  30. case "RESET_TIMER":
  31. return {
  32. ...state,baseTime: 0,startedAt: state.startedAt ? action.now : undefined,stoppedAt: state.stoppedAt ? action.now : undefined
  33. };
  34. case "START_TIMER":
  35. return {
  36. ...state,baseTime: action.baseTime,startedAt: action.now,stoppedAt: undefined
  37. };
  38. case "STOP_TIMER":
  39. return {
  40. ...state,stoppedAt: action.now
  41. }
  42. default:
  43. return state;
  44. }
  45. }
  46.  
  47. const store = createStore(reducer);

请注意,操作创建者和缩减器仅处理原始值,并且不使用任何间隔或TICK操作类型.现在,一个组件可以轻松地订阅这些数据,并按照需要进行更新:

  1. // Helper function that takes store state
  2. // and returns the current elapsed time
  3. function getElapsedTime(baseTime,startedAt,stoppedAt = new Date().getTime()) {
  4. if (!startedAt) {
  5. return 0;
  6. } else {
  7. return stoppedAt - startedAt + baseTime;
  8. }
  9. }
  10.  
  11. class Timer extends React.Component {
  12. componentDidMount() {
  13. this.interval = setInterval(this.forceUpdate.bind(this),this.props.updateInterval || 33);
  14. }
  15.  
  16. componentWillUnmount() {
  17. clearInterval(this.interval);
  18. }
  19.  
  20. render() {
  21. const { baseTime,stoppedAt } = this.props;
  22. const elapsed = getElapsedTime(baseTime,stoppedAt);
  23.  
  24. return (
  25. <div>
  26. <div>Time: {elapsed}</div>
  27. <div>
  28. <button onClick={() => this.props.startTimer(elapsed)}>Start</button>
  29. <button onClick={() => this.props.stopTimer()}>Stop</button>
  30. <button onClick={() => this.props.resetTimer()}>Reset</button>
  31. </div>
  32. </div>
  33. );
  34. }
  35. }
  36.  
  37. function mapStateToProps(state) {
  38. const { baseTime,stoppedAt } = state;
  39. return { baseTime,stoppedAt };
  40. }
  41.  
  42. Timer = ReactRedux.connect(mapStateToProps,{ startTimer,stopTimer,resetTimer })(Timer);

您甚至可以在不同更新频率的同一数据上显示多个定时器:

  1. class Application extends React.Component {
  2. render() {
  3. return (
  4. <div>
  5. <Timer updateInterval={33} />
  6. <Timer updateInterval={1000} />
  7. </div>
  8. );
  9. }
  10. }

您可以在这里看到一个working JSBinhttps://jsbin.com/dupeji/12/edit?js,output

猜你在找的JavaScript相关文章