一次性工作定时器
One-time working timer
我觉得自己很困惑,因为我从昨天开始还在处理这个问题,但没有任何帮助。
所以,问题:我有待办事项列表。每个任务都有计时器。同一时间只能有一个计时器工作,因此用户同一时间只能执行一项任务。
我以为我可以在另一个任务中禁用 'Start' 按钮,当其中一个计时器 运行 时,但我认为我在 setState 中犯了错误,因为所有计时器仍然 运行 在一起 = (
我阅读了文档,但对我没有帮助。
另外,我有文件 TodoTextInput,它生成这些任务,我想也许我应该在这里粘贴我的计时器,但这很奇怪。
为了获得完整信息,我在这里留下了两个文件。
感谢您的帮助!
TodoItem (问题在这里)
import React, { Component, PropTypes } from 'react'
import classnames from 'classnames'
import TodoTextInput from './TodoTextInput'
export default class TodoItem extends Component {
constructor(props) {
super(props);
this.state = { secondsStart: this.props.minSeconds, timerRunning: false }
}
static propTypes = {
todo: PropTypes.object.isRequired,
deleteTodo: PropTypes.func.isRequired,
completeTodo: PropTypes.func.isRequired,
}
static defaultProps = {
minSeconds: 0
}
handleSave = (id, text) => {
if (text.length === 0) {
this.props.deleteTodo(id)
}
}
handleStartClick = () => {
if (!this.state.timerRunning) {
this.incrementer = setInterval(() => {
this.setState({
secondsStart: (this.state.secondsStart + 1)
});
}, 1000)
this.setState({
timerRunning: true,
currentTodoId: this.props.todo.id,
runningTodoId: this.props.todo.id
});
}
}
getSeconds = () => {
return ('0' + this.state.secondsStart % 60).slice(-2)
}
getMinutes = () => {
return Math.floor((this.state.secondsStart / 60)%60)
}
getHoures = () => {
return Math.floor((this.state.secondsStart / 3600)%24)
}
handleStopClick = () => {
clearInterval(this.incrementer)
this.setState({ timerRunning: false, currentTodoId: null, runningTodoId: null });
}
render() {
const { todo, completeTodo, deleteTodo} = this.props
const element = this.state.todo ? (
<TodoTextInput text={todo.text}
onSave={(text) => this.handleSave(todo.id, text)} />
) : (
<div className="view">
<input className="toggle"
type="checkbox"
checked={todo.completed}
onChange={() => completeTodo(todo.isRequired)} />
<label>
{todo.text}
</label>
<div className="buttons">
<h6>{this.getHoures()}:{this.getMinutes()}:{this.getSeconds()}</h6>
{(this.state.secondsStart === 0)
? <button className="timer-start" onClick={this.handleStartClick} disabled={this.state.timerRunning }>Start</button>
: <button className="timer-stop" onClick={this.handleStopClick} disabled={!this.state.timerRunning && this.state.runningTodoId !== this.state.currentTodoId}>Stop</button>
}
</div>
<button className="destroy"
onClick={() => deleteTodo(todo.id)} />
</div>
)
return (
<li className={classnames({
completed: todo.completed,
})}>
{element}
</li>
)
}
}
TodoTextInput (以防万一)
import React, { Component, PropTypes } from 'react'
import classnames from 'classnames'
export default class TodoTextInput extends Component {
static propTypes = {
onSave: PropTypes.func.isRequired,
text: PropTypes.string,
placeholder: PropTypes.string,
newTodo: PropTypes.bool
}
state = {
text: this.props.text || ''
}
handleSubmit = e => {
const text = e.target.value.trim()
if (e.which === 13) {
this.props.onSave(text)
if (this.props.newTodo) {
this.setState({ text: '' })
}
}
}
handleChange = e => {
this.setState({ text: e.target.value })
}
handleBlur = e => {
if (!this.props.newTodo) {
this.props.onSave(e.target.value)
}
}
render() {
return (
<input className={
classnames({
'new-todo': this.props.newTodo
})}
type="text"
placeholder={this.props.placeholder}
autoFocus="true"
value={this.state.text}
onBlur={this.handleBlur}
onChange={this.handleChange}
onKeyDown={this.handleSubmit} />
)
}
}
有很多方法可以做到这一点。您可以 将当前 运行 计时器的 ID 存储在 MainSection
的状态中,并使用 TodoItem
回调函数将其更改为 completeTodo
。然后,您可以将 MainSection
状态的这个属性作为道具发送给每个 TodoItem
并检查它是否是 运行:
render() {
const { todo, runningTodoId, startTodoTimer, completeTodo, deleteTodo} = this.props
let disable = runningTodoId == todo.id;
}
重点是你需要与 MainSection
沟通,其中 TodoItem
是 运行 或者至少如果有 TodoItem
运行 .据我所知,您所存储的有关计时器状态的所有信息都针对 TodoItem
的状态,因此其他 TodoItems
无法知道它们是否应该能够启动.
TODO 列表是 almost a classic example of the Redux usage。我不知道您是否可以将 Redux 引入您的应用程序,但在存储全局状态时它绝对是一个很棒的工具。
我觉得自己很困惑,因为我从昨天开始还在处理这个问题,但没有任何帮助。 所以,问题:我有待办事项列表。每个任务都有计时器。同一时间只能有一个计时器工作,因此用户同一时间只能执行一项任务。 我以为我可以在另一个任务中禁用 'Start' 按钮,当其中一个计时器 运行 时,但我认为我在 setState 中犯了错误,因为所有计时器仍然 运行 在一起 = ( 我阅读了文档,但对我没有帮助。 另外,我有文件 TodoTextInput,它生成这些任务,我想也许我应该在这里粘贴我的计时器,但这很奇怪。
为了获得完整信息,我在这里留下了两个文件。 感谢您的帮助!
TodoItem (问题在这里)
import React, { Component, PropTypes } from 'react'
import classnames from 'classnames'
import TodoTextInput from './TodoTextInput'
export default class TodoItem extends Component {
constructor(props) {
super(props);
this.state = { secondsStart: this.props.minSeconds, timerRunning: false }
}
static propTypes = {
todo: PropTypes.object.isRequired,
deleteTodo: PropTypes.func.isRequired,
completeTodo: PropTypes.func.isRequired,
}
static defaultProps = {
minSeconds: 0
}
handleSave = (id, text) => {
if (text.length === 0) {
this.props.deleteTodo(id)
}
}
handleStartClick = () => {
if (!this.state.timerRunning) {
this.incrementer = setInterval(() => {
this.setState({
secondsStart: (this.state.secondsStart + 1)
});
}, 1000)
this.setState({
timerRunning: true,
currentTodoId: this.props.todo.id,
runningTodoId: this.props.todo.id
});
}
}
getSeconds = () => {
return ('0' + this.state.secondsStart % 60).slice(-2)
}
getMinutes = () => {
return Math.floor((this.state.secondsStart / 60)%60)
}
getHoures = () => {
return Math.floor((this.state.secondsStart / 3600)%24)
}
handleStopClick = () => {
clearInterval(this.incrementer)
this.setState({ timerRunning: false, currentTodoId: null, runningTodoId: null });
}
render() {
const { todo, completeTodo, deleteTodo} = this.props
const element = this.state.todo ? (
<TodoTextInput text={todo.text}
onSave={(text) => this.handleSave(todo.id, text)} />
) : (
<div className="view">
<input className="toggle"
type="checkbox"
checked={todo.completed}
onChange={() => completeTodo(todo.isRequired)} />
<label>
{todo.text}
</label>
<div className="buttons">
<h6>{this.getHoures()}:{this.getMinutes()}:{this.getSeconds()}</h6>
{(this.state.secondsStart === 0)
? <button className="timer-start" onClick={this.handleStartClick} disabled={this.state.timerRunning }>Start</button>
: <button className="timer-stop" onClick={this.handleStopClick} disabled={!this.state.timerRunning && this.state.runningTodoId !== this.state.currentTodoId}>Stop</button>
}
</div>
<button className="destroy"
onClick={() => deleteTodo(todo.id)} />
</div>
)
return (
<li className={classnames({
completed: todo.completed,
})}>
{element}
</li>
)
}
}
TodoTextInput (以防万一)
import React, { Component, PropTypes } from 'react'
import classnames from 'classnames'
export default class TodoTextInput extends Component {
static propTypes = {
onSave: PropTypes.func.isRequired,
text: PropTypes.string,
placeholder: PropTypes.string,
newTodo: PropTypes.bool
}
state = {
text: this.props.text || ''
}
handleSubmit = e => {
const text = e.target.value.trim()
if (e.which === 13) {
this.props.onSave(text)
if (this.props.newTodo) {
this.setState({ text: '' })
}
}
}
handleChange = e => {
this.setState({ text: e.target.value })
}
handleBlur = e => {
if (!this.props.newTodo) {
this.props.onSave(e.target.value)
}
}
render() {
return (
<input className={
classnames({
'new-todo': this.props.newTodo
})}
type="text"
placeholder={this.props.placeholder}
autoFocus="true"
value={this.state.text}
onBlur={this.handleBlur}
onChange={this.handleChange}
onKeyDown={this.handleSubmit} />
)
}
}
有很多方法可以做到这一点。您可以 将当前 运行 计时器的 ID 存储在 MainSection
的状态中,并使用 TodoItem
回调函数将其更改为 completeTodo
。然后,您可以将 MainSection
状态的这个属性作为道具发送给每个 TodoItem
并检查它是否是 运行:
render() {
const { todo, runningTodoId, startTodoTimer, completeTodo, deleteTodo} = this.props
let disable = runningTodoId == todo.id;
}
重点是你需要与 MainSection
沟通,其中 TodoItem
是 运行 或者至少如果有 TodoItem
运行 .据我所知,您所存储的有关计时器状态的所有信息都针对 TodoItem
的状态,因此其他 TodoItems
无法知道它们是否应该能够启动.
TODO 列表是 almost a classic example of the Redux usage。我不知道您是否可以将 Redux 引入您的应用程序,但在存储全局状态时它绝对是一个很棒的工具。