我可能會建議要對此有所不同:只存儲所需要的狀態,計算在店裏消耗的時間,並讓組件設置其自己間隔但是他們經常希望更新顯示。
這將操作調度保持在最低限度 - 僅調度啓動和停止(以及重置)計時器的操作。請記住,您每次都會返回一個新的狀態對象您分派一個操作,然後每個connect
ed組件重新呈現(儘管它們使用優化以避免在被包裝的組件內進行太多重新呈現)。此外,很多許多操作調度都可能使調試應用程序狀態更改變得困難,因爲您必須處理所有的TICK
以及其他操作。
下面是一個例子:
// Action Creators
function startTimer(baseTime = 0) {
return {
type: "START_TIMER",
baseTime: baseTime,
now: new Date().getTime()
};
}
function stopTimer() {
return {
type: "STOP_TIMER",
now: new Date().getTime()
};
}
function resetTimer() {
return {
type: "RESET_TIMER",
now: new Date().getTime()
}
}
// Reducer/Store
const initialState = {
startedAt: undefined,
stoppedAt: undefined,
baseTime: undefined
};
function reducer(state = initialState, action) {
switch (action.type) {
case "RESET_TIMER":
return {
...state,
baseTime: 0,
startedAt: state.startedAt ? action.now : undefined,
stoppedAt: state.stoppedAt ? action.now : undefined
};
case "START_TIMER":
return {
...state,
baseTime: action.baseTime,
startedAt: action.now,
stoppedAt: undefined
};
case "STOP_TIMER":
return {
...state,
stoppedAt: action.now
}
default:
return state;
}
}
const store = createStore(reducer);
通知動作創作者和減速器僅涉及原始值,並且不使用任何種類的間隔或TICK
動作類型。現在,一個組件可以輕鬆地訂閱這個數據和它要更新的次數:
// Helper function that takes store state
// and returns the current elapsed time
function getElapsedTime(baseTime, startedAt, stoppedAt = new Date().getTime()) {
if (!startedAt) {
return 0;
} else {
return stoppedAt - startedAt + baseTime;
}
}
class Timer extends React.Component {
componentDidMount() {
this.interval = setInterval(this.forceUpdate.bind(this), this.props.updateInterval || 33);
}
componentWillUnmount() {
clearInterval(this.interval);
}
render() {
const { baseTime, startedAt, stoppedAt } = this.props;
const elapsed = getElapsedTime(baseTime, startedAt, stoppedAt);
return (
<div>
<div>Time: {elapsed}</div>
<div>
<button onClick={() => this.props.startTimer(elapsed)}>Start</button>
<button onClick={() => this.props.stopTimer()}>Stop</button>
<button onClick={() => this.props.resetTimer()}>Reset</button>
</div>
</div>
);
}
}
function mapStateToProps(state) {
const { baseTime, startedAt, stoppedAt } = state;
return { baseTime, startedAt, stoppedAt };
}
Timer = ReactRedux.connect(mapStateToProps, { startTimer, stopTimer, resetTimer })(Timer);
你甚至可以用不同的更新頻率顯示相同數據的多個計時器:
class Application extends React.Component {
render() {
return (
<div>
<Timer updateInterval={33} />
<Timer updateInterval={1000} />
</div>
);
}
}
你可以看到一個working JSBin與這個實施在這裏:https://jsbin.com/dupeji/12/edit?js,output
我對我已故的評論表示歉意,但非常感謝!通過閱讀所有這些,真的幫助我更好地理解如何構建/設計所有這些。如果你不介意,我有兩個問題。首先是爲什麼上面的代碼不工作,如果我使用'null'而不是'undefined'?其次,我對'clearInterval(this.interval)'這一行有點不確定。 'this.interval'定義在哪裏?還是你的意思是在它上面執行'this.interval = setInterval()'?再次感謝你的意思很多,你會竭盡全力去做到這一點! – saadq
@meh_programmer我使用了'undefined',所以'getElapsedTime'中的默認參數起作用(傳遞undefined使其使用默認值,但傳遞null時不是這種情況)。你是對的 - 我會解決的! :) –
快速注:看來你有減速非純函數:新的Date():「這是非常重要的是,減速保持純粹的東西,你不應該做機內部......。」從文檔 的https: //github.com/reactjs/redux/blob/master/docs/basics/Reducers.md 我認爲最佳實踐是在ActionCreators中擁有所有的雜質 https://github.com/reactjs/redux/issues/1088 –