Я пытаюсь исправить некоторые проблемы, связанные с Реагировать JS. В настоящее время работаю над ускоренным курсом и пытаюсь улучшить todoList. Я очень новичок, и, надеюсь, это может дать мне новую перспективу после 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} />
))*/
);
}
}
@Vencovsky Большое спасибо, я все еще новичок. Я обновил код, чтобы отобразить то, что, как мне кажется, вы упомянули.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Я немного почистил беспорядок в вашем коде, и теперь он работает для меня:
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>
);
}
}
Некоторые комментарии к вашему коду:
Todos в качестве свойства для TodoItem, но вы не установили это свойство при использовании TodoItem, и поскольку вы установили его как требуется с .isRequired, возникла первая ошибка.undefined на какую-то функцию. Вы не вставили свой код с этой функцией, поэтому я не могу сказать, что именно пошло не так, но я думаю, что проблема в привязке функций markComplete и delTodo, которые вы предоставили TodoItem через проп. Обычно это привязывает объект this к текущему контексту выполнения (в данном случае классу TodoItem), и поскольку TodoItem не имеет функций-членов markComplete и самого delTodo, привязка возвращает для них undefined.Todos и TodoItem у вас нет состояния, поэтому лучше используйте функциональные компоненты без состояния (намного более компактные).Эй, извините за поздний ответ, эти комментарии были действительно приятными и полезными, большое спасибо :) !!
Покажите нам, где вы вызываете этот компонент в своем коде, как вы передаете ему свойства и как вы манипулируете им.