我正在努力解决有关 React JS 的一些问题。目前正在参加速成类(class),并且我一直在努力改进待办事项列表。我是个新手,希望在经过 8 小时的故障排除后,这可以给我带来新的视角。
我的代码 - 输入:
export class TodoItem extends Component {
getStyle = () => {
return {
background: '#233D4D',
padding: '15px',
borderBottom: '1px darkgray Ridge',
textDecoration: this.props.todo.completed ? 'line-through' :
'none',
color: this.props.todo.completed ? 'lightgreen' : 'white',
fontWeight: this.props.todo.completed ? 'bold' : 'none',
}
}
render() {
const { title } = this.props.todo;
return (
<div style={this.getStyle()}>
<p>
<input type="checkbox" onChange= .
{this.props.markComplete.bind(this)} checked= .
{this.props.todo.completed} /> {' '}
{title}
<button style={btnStyle} onClick= .
{this.props.delTodo.bind(this)}><FontAwesomeIcon size="2x" icon= .
{faTrash} /></button>
</p>
</div>
)
}
}
// PropTypes
TodoItem.propTypes = {
Todos: PropTypes.array.isRequired,
markComplete: PropTypes.func.isRequired,
delTodo: PropTypes.func.isRequired
}
我的代码 - 失败的 propType:
render() {
const { title } = this.props.todo;
return (
<div style={this.getStyle()}>
<p>
<input type="checkbox"
onChange={this.props.markComplete.bind(this)}
checked={this.props.todo.completed} /> {' '}
{title}
<button style={btnStyle}
onClick={this.props.delTodo.bind(this)}>
<FontAwesomeIcon size="2x" icon={faTrash} />
</button>
</p>
</div>
)
}
// PropTypes
TodoItem.propTypes = {
Todos: PropTypes.array.isRequired,
markComplete: PropTypes.func.isRequired,
delTodo: PropTypes.func.isRequired
}
这是我的问题:
#1 - Prop Types
index.js:1446 Warning: Failed prop type: The prop `Todos` is marked as required in `TodoItem`, but its value is `undefined`.
in TodoItem (at Todos.js:12)
#2 - Component changing an uncontrolled input
Warning: A component is changing an uncontrolled input of type text to
be controlled. Input elements should not switch from uncontrolled to
controlled (or vice versa). Decide between using a controlled or
uncontrolled input element for the lifetime of the component.`
========编辑=========
这里是调用组件、传递属性和操作的地方:
render() {
return (
<Router>
<div className="App">
<div className="container">
<Header />
<Route exact path="/" render={props => (
<React.Fragment>
<AddTodo addTodo={this.addTodo} />
<Todos todos={this.state.todo} markComplete= .
{this.markComplete}
delTodo={this.delTodo} />
</React.Fragment>
)} />
<Route path="/about" component={About} />
</div>
</div>
</Router>
);
class Todos extends Component {
render() {
// Mangler håndtering af ingen elementer
let output = undefined;
if(this.props.todos && this.props.todos.length > 0){
// lav object
let output = this.props.todos.map((todo) => (
<TodoItem key={todo.id} todo={todo} markComplete=
{this.props.markComplete} delTodo={this.props.delTodo} />
))
return output;
}
return (
<div>
{output}
</div>
/*this.props.todos.map((todo) => (
<TodoItem key={todo.id} todo={todo} markComplete=
{this.props.markComplete} delTodo={this.props.delTodo} />
))*/
);
}
}
最佳答案
我清理了你代码中的困惑部分,它现在对我有用:
const TodoItem = ({title, completed, delTodo, markComplete}) => (
<div>
<p>
<input type="checkbox" onChange={markComplete} checked={completed} />
{title}
<button onClick={delTodo}>Delete</button>
</p>
</div>
);
TodoItem.propTypes = {
title: PropTypes.string.isRequired,
completed: PropTypes.bool.isRequired,
markComplete: PropTypes.func.isRequired,
delTodo: PropTypes.func.isRequired
};
class Todos extends Component {
constructor(props) {
super(props);
this.state = {
todos: [
{id: 1, title: "First", completed: false},
{id: 2, title: "Second", completed: false},
{id: 3, title: "Third", completed: true}
]
};
}
markComplete = id => {
const index = this.state.todos.findIndex(t => t.id === id);
if (index > -1) {
const modifiedTodos = JSON.parse(JSON.stringify(this.state.todos));
modifiedTodos[index].completed = true;
this.setState({todos: modifiedTodos});
}
};
delTodo = id => {
const index = this.state.todos.findIndex(t => t.id === id);
if (index > -1) {
const modifiedTodos = JSON.parse(JSON.stringify(this.state.todos));
modifiedTodos.splice(index, 1);
this.setState({todos: modifiedTodos});
}
};
render() {
return (
<div>
{this.state.todos
? this.state.todos.map(todo => (
<TodoItem
key={todo.id}
title={todo.title}
completed={todo.completed}
markComplete={() => this.markComplete(todo.id)}
delTodo={() => this.delTodo(todo.id)}
/>
))
: null}
</div>
);
}
}
关于您的代码的一些评论:
- [第一个错误]:通过 propTypes,您将
Todos
作为TodoItem
的属性,但在使用TodoItem
时没有设置该属性因为您使用.isRequired
按要求设置了它,所以抛出了第一个错误。 - [第二个错误]:据我所知,当更改处理程序从
undefined
更改为某个函数时,就会发生从不受控输入更改为受控输入的情况。您没有使用该函数粘贴代码,所以我无法判断到底出了什么问题,但我认为问题出在函数markComplete
和delTodo
的绑定(bind)上> 您通过 prop 提供了TodoItem
。通常这会将this
对象绑定(bind)到当前执行上下文(在本例中为类TodoItem
),并且因为TodoItem
没有成员函数markComplete
和delTodo
本身,绑定(bind)会为它们返回undefined
。 - 下次您发布问题时,请尝试编写一个最小工作示例 (MWE)。你的代码确实充满了不相关的东西。删除它,SO 的人们会更乐意帮助您。
- 在您的类
Todos
和TodoItem
中,您没有任何状态,因此最好使用无状态函数组件(更加紧凑)。 - 在某些地方,您使用空格和点分隔属性名称和属性值。
关于javascript - React JS 警告 : Failed propType and uncontrolled input,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55280382/