我如何在 React 中触发几个组件更高的功能?
How do I trigger a function several components higher in React?
刚学React,想在font awesome icon上加个onClick
,运行加个markTaskAsCompleted
功能。我遇到了麻烦,因为它是层次结构中较低的几个组件。你会如何理想地去做这件事?请记住,我还必须在函数中传递任务的 ID。
class TasksBase extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: false,
tasks: [],
};
}
componentDidMount() {
this.onListenForTasks();
}
onListenForTasks() {
this.setState({ loading: true });
this.unsubscribe = this.props.firebase
.tasks()
.orderBy('created', 'desc')
.onSnapshot(snapshot => {
if (snapshot.size) {
let tasks = [];
snapshot.forEach(doc =>
tasks.push({ ...doc.data(), uid: doc.id }),
);
this.setState({
tasks: tasks,
loading: false
});
} else {
this.setState({ tasks: null, loading: false });
}
});
}
markTaskAsCompleted(){
console.log("Completed");
}
componentWillUnmount() {
this.unsubscribe();
}
render() {
const { tasks, loading } = this.state;
return (
<div>
{loading && <div>Loading ...</div>}
{tasks ? (
<TaskList tasks={tasks} />
):(
<div>There are no tasks ...</div>
)}
</div>
);
}
}
const Tasks = withFirebase(TasksBase);
const TaskList = ({ tasks }) => (
<ul className="tasks">
{tasks.map( task => (
<Task key={task.uid} task={task} />
))}
</ul>
);
const Task = ({ task }) => (
(!task.completed && !task.obsolete && !task.waitingForDependencies) &&
<li className="task">
<strong>{task.userId}</strong> {task.name}
<div className="icons">
<FontAwesomeIcon icon="check-circle"/>
<FontAwesomeIcon icon="times-circle" />
</div>
</li>
);
const condition = authUser => !!authUser;
export default compose(
withEmailVerification,
withAuthorization(condition),
)(Tasks);
您需要将其作为
传递到树下
markTaskAsCompleted={this.props.markTaskAsCompleted}
并确保该函数在构造函数中绑定到父级。
您可以使用 refs 或 document.getElementById 获取 ID。
在构造函数中绑定您的 class 函数:
this.markTaskAsCompleted = this.markTaskAsCompleted.bind(this);
使用 props 将函数传递到子组件中:
<TaskList tasks={tasks} handleMarkCompleted={this.markTaskAsCompleted} />
再次将函数传递给子组件,这是 prop drilling,不是最新最好的方法,但它有效:
const TaskList = ({ tasks, handleMarkCompleted }) => (
<ul className="tasks">
{tasks.map( task => (
<Task key={task.uid} task={task} handleMarkCompleted={handleMarkCompleted} />
))}
</ul>
);
触发函数onClick
:
inside <Task>...
<FontAwesomeIcon icon="check-circle" onClick={() => handleMarkCompleted(task.uid)} />
如果将数据传递到函数中(例如 task.uid
),请在函数定义中也将其作为参数,以便您可以使用它:
markTaskAsCompleted(id){
console.log("Completed", id);
}
刚学React,想在font awesome icon上加个onClick
,运行加个markTaskAsCompleted
功能。我遇到了麻烦,因为它是层次结构中较低的几个组件。你会如何理想地去做这件事?请记住,我还必须在函数中传递任务的 ID。
class TasksBase extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: false,
tasks: [],
};
}
componentDidMount() {
this.onListenForTasks();
}
onListenForTasks() {
this.setState({ loading: true });
this.unsubscribe = this.props.firebase
.tasks()
.orderBy('created', 'desc')
.onSnapshot(snapshot => {
if (snapshot.size) {
let tasks = [];
snapshot.forEach(doc =>
tasks.push({ ...doc.data(), uid: doc.id }),
);
this.setState({
tasks: tasks,
loading: false
});
} else {
this.setState({ tasks: null, loading: false });
}
});
}
markTaskAsCompleted(){
console.log("Completed");
}
componentWillUnmount() {
this.unsubscribe();
}
render() {
const { tasks, loading } = this.state;
return (
<div>
{loading && <div>Loading ...</div>}
{tasks ? (
<TaskList tasks={tasks} />
):(
<div>There are no tasks ...</div>
)}
</div>
);
}
}
const Tasks = withFirebase(TasksBase);
const TaskList = ({ tasks }) => (
<ul className="tasks">
{tasks.map( task => (
<Task key={task.uid} task={task} />
))}
</ul>
);
const Task = ({ task }) => (
(!task.completed && !task.obsolete && !task.waitingForDependencies) &&
<li className="task">
<strong>{task.userId}</strong> {task.name}
<div className="icons">
<FontAwesomeIcon icon="check-circle"/>
<FontAwesomeIcon icon="times-circle" />
</div>
</li>
);
const condition = authUser => !!authUser;
export default compose(
withEmailVerification,
withAuthorization(condition),
)(Tasks);
您需要将其作为
传递到树下markTaskAsCompleted={this.props.markTaskAsCompleted}
并确保该函数在构造函数中绑定到父级。
您可以使用 refs 或 document.getElementById 获取 ID。
在构造函数中绑定您的 class 函数:
this.markTaskAsCompleted = this.markTaskAsCompleted.bind(this);
使用 props 将函数传递到子组件中:
<TaskList tasks={tasks} handleMarkCompleted={this.markTaskAsCompleted} />
再次将函数传递给子组件,这是 prop drilling,不是最新最好的方法,但它有效:
const TaskList = ({ tasks, handleMarkCompleted }) => (
<ul className="tasks">
{tasks.map( task => (
<Task key={task.uid} task={task} handleMarkCompleted={handleMarkCompleted} />
))}
</ul>
);
触发函数onClick
:
inside <Task>...
<FontAwesomeIcon icon="check-circle" onClick={() => handleMarkCompleted(task.uid)} />
如果将数据传递到函数中(例如 task.uid
),请在函数定义中也将其作为参数,以便您可以使用它:
markTaskAsCompleted(id){
console.log("Completed", id);
}