【发布时间】:2020-11-21 13:07:59
【问题描述】:
// 编辑 --
这可能会有所帮助: Project Hatchways
问题链接 - Issue
就目前的代码而言,标签的结果仍未呈现结果。
我有一个组件 App.js 可以渲染一些子元素。其中之一是 2 个搜索栏。第二个搜索栏TagSearch 应该呈现标签创建的结果。我想要做的是从标签所在的Student 传递数据,并将它们传递给 App 组件,以便将它们注入我的 Fuse 实例以便搜索它们。我试图在 App.js 中创建一个函数update,然后将其传递给 Student.js,以便在用户搜索标签时在父级中更新标签。出于某种原因,我收到一个 TypeError,指出 update 不是函数。
我放入控制台日志以跟踪标签出现的位置。这些标签在 Student.js 中看起来非常好,但是当我在 App.js 中控制台记录它们时,这些标签只是显示为一个空数组,这告诉我它们没有正确地从 Student.js 向上传递组件树到 App。 js.
// App.js
import axios from "axios";
import Fuse from "fuse.js";
import Student from "./components/Student";
import Search from "./components/Search";
import TagSearch from "./components/TagSearch";
import "./App.css";
function App() {
const [loading, setLoading] = useState(true);
const [students, setStudents] = useState([]);
const [query, updateQuery] = useState("");
const [tags, setTags] = useState([]);
const [tagQuery, setTagQuery] = useState("");
console.log("tags from app: ", tags);
const getStudents = async () => {
setLoading(true);
try {
const url = `private url for assignment`;
const response = await axios.get(url);
setStudents(response.data.students);
setLoading(false);
} catch (err) {
console.log("Error: ", err);
}
};
const fuse = new Fuse(students, {
keys: ["firstName", "lastName"],
includeMatches: true,
minMatchCharLength: 2,
});
const tagFuse = new Fuse(tags, {
keys: ["text", "id"],
includesMatches: true,
minMatchCharLength: 2,
});
function handleChange(e) {
updateQuery(e.target.value);
}
function handleTags(e) {
setTagQuery(e.target.value);
}
const results = fuse.search(query);
const studentResults = query ? results.map((s) => s.item) : students;
const tagResults = tagFuse.search(tagQuery);
const taggedResults = tagQuery ? tagResults.map((s) => s.item) : tags;
const update = (t) => {
t = tags; // changed this to make sure t is tags from this component's state
setTags(t);
};
useEffect(() => {
getStudents();
}, []);
if (loading) return "Loading ...";
return (
<div className="App">
<main>
<Search query={query} handleChange={handleChange} />
<TagSearch query={tagQuery} handleTags={handleTags} />
{studentResults &&
studentResults.map((s, key) => <Student key={key} students={s} update={update} />)}
{taggedResults &&
taggedResults.map((s, key) => (
<Student key={key} students={s} update={update} />
))}
</main>
</div>
);
}
export default App;
// Student.js
import Collapsible from "../components/Collapsible";
import findAverage from "../helpers/findAverage";
import Styles from "../styles/StudentStyles";
const KeyCodes = {
comma: 188,
enter: 13,
};
const delimiters = [KeyCodes.comma, KeyCodes.enter];
const Student = ({ students, update }) => {
const [isOpened, setIsOpened] = useState(false);
const [tags, setTags] = useState([]);
const collapse = () => {
setIsOpened(!isOpened);
};
const handleDelete = (i) => {
const deleted = tags.filter((tag, index) => index !== i);
setTags(deleted);
};
const handleAddition = (tag, i) => {
setTags([...tags, tag]);
};
useEffect(() => {
update(tags);
}, []);
return (
<Styles>
<div className="student-container">
<img src={students.pic} alt={students.firstName} />
<div className="student-details">
<h1>
{students.firstName} {students.lastName}
</h1>
<p>Email: {students.email}</p>
<p>Company: {students.company}</p>
<p>Skill: {students.skill}</p>
<p>Average: {findAverage(students.grades)}</p>
<Collapsible
students={students}
delimiters={delimiters}
handleDelete={handleDelete}
handleAddition={handleAddition}
isOpened={isOpened}
tags={tags}
/>
</div>
</div>
<button onClick={collapse}>+</button>
</Styles>
);
};
export default Student;
【问题讨论】:
-
我立即注意到的是,当有搜索结果时创建的
Student组件没有传递更新函数。然而,useEffect在第一次渲染时仍会调用update。 -
@CoryHarper 所以我很困惑。我是否应该用更新函数将搜索结果包装在
App.js中,然后传递更新函数,并留下useEffect? -
对您的
Student组件进行健全性检查,console.log(update) -
我认为@Cory Harper 的意思是简单地将
update作为道具传递。 -
您可以简单地添加一个回调函数,当您将数据从
student发送到app时,该回调函数将被触发,然后在该回调中更改父级的状态跨度>
标签: reactjs state parent-child