React子组件向父组件传props报错:props.setTagsinput不是函数
问题分析与解决方案
错误根源
props.setTagsinput is not a function报错原因:Student.js中使用<TagsInput />时未传递setTagsinput属性,导致该组件实例的props中不存在这个函数,调用时触发错误。- 潜在无限重渲染风险:
TagsInput.js中直接在组件顶层调用props.setTagsinput(tags),会在每次组件渲染时执行,可能引发无限重渲染循环。
分步解决
1. 修复 TagsInput 组件的调用逻辑
修改 TagsInput.js,仅在 setTagsinput 存在时调用,且通过 useEffect 监听 tags 变化,避免无效重复调用:
import React from "react"; const TagsInput = (props) => { // 支持接收初始标签,适配不同场景 const [tags, setTags] = React.useState(props.initialTags || []); // 仅在tags变化且setTagsinput存在时,向父组件传递数据 React.useEffect(() => { if (typeof props.setTagsinput === 'function') { props.setTagsinput(tags); } }, [tags, props.setTagsinput]); const addTags = event => { if (event.key === "Enter" && event.target.value.trim() !== "") { setTags([...tags, event.target.value.trim()]); event.target.value = ""; } }; const removeTags = index => { setTags(tags.filter((_, idx) => idx !== index)); }; return ( <div className="tags-input"> <div className="tags_section"> {tags.map((tag, index) => ( <div className="tag tag-flex" key={index}> <p className="tag-p">{tag}</p> {/* 补充删除按钮逻辑,完善交互 */} <button onClick={() => removeTags(index)}>×</button> </div> ))} </div> <input type="text" onKeyUp={addTags} placeholder="Press enter to add tags" /> </div> ); }; export default TagsInput;
2. 处理 Student 组件中的 TagsInput 实例
如果每个学生需要独立维护标签并同步到 Top 组件,修改如下:
Top.js:添加学生标签状态管理
import React, {useState, useEffect} from 'react'; import axios from 'axios'; import Student from './Student'; import TagsInput from "./TagsInput"; const Top = () => { const [ posts, setPosts] = useState([]); const [ allPosts, setAllPosts] = useState([]); const [searchKeyword, setSearchKeyword] = React.useState(""); const [searchTagKeyword, setTagSearchKeyword] = React.useState(""); // 初始化时为每个学生添加tags属性 useEffect(() => { axios.get('xxx.com') .then(result => { const studentsWithTags = result.data.students.map(student => ({ ...student, tags: [] })); setPosts(studentsWithTags); setAllPosts(studentsWithTags); if (searchKeyword) { getSearchResult() } })}, [searchKeyword]); // 更新指定学生的标签 const updateStudentTags = (studentId, newTags) => { setPosts(prev => prev.map(student => student.id === studentId ? {...student, tags: newTags} : student )); setAllPosts(prev => prev.map(student => student.id === studentId ? {...student, tags: newTags} : student )); }; const getSearchResult = () => { const result = allPosts.filter(output => { const fullName = `${output.firstName} ${output.lastName}`.toLowerCase(); return fullName.includes(searchKeyword.toLowerCase()); }); setPosts(result); }; const getTagSearchResult = () => { const result = allPosts.filter(output => output.tags.some(tag => tag.toLowerCase().includes(searchTagKeyword.toLowerCase())) ); setPosts(result); }; // 监听标签搜索关键词变化,触发搜索 useEffect(() => { getTagSearchResult(); }, [searchTagKeyword]); return ( <div> {/* 顶部全局标签输入(如果需要) */} <TagsInput setTagsinput={(tags) => console.log('全局标签:', tags)} /> <div> <input className="search-box" placeholder="搜索姓名" value={searchKeyword} onChange={(e) => setSearchKeyword(e.target.value)}/> </div> <div> {/* 修复标签搜索的onChange绑定错误 */} <input className="search-box" placeholder="搜索标签" value={searchTagKeyword} onChange={(e) => setTagSearchKeyword(e.target.value)}/> </div> <div> {searchKeyword && <p>{searchKeyword} 搜索结果</p>} {posts.length > 0 ? posts.map((data) => <Student key={data.id} data={data} updateTags={(newTags) => updateStudentTags(data.id, newTags)} /> ) : <div><p>未找到匹配结果!</p></div> } </div> </div> ); } export default Top;
Student.js:传递标签更新函数
import React, {useState} from 'react'; import TagsInput from './TagsInput'; const Student = (props) => { const [show, setShow] = useState(false); const gradesAverage = (grades) => { const sum = grades.reduce((acc, score) => acc + Number(score), 0); return (sum / grades.length).toFixed(1); }; return ( <div className="flex"> <div className="image"> <img src={props.data.pic} className="profile" alt={`${props.data.firstName} ${props.data.lastName}`} /> </div> <div> <p className="name">{props.data.firstName} {props.data.lastName}</p> <button className="button" onClick={() => setShow(!show)}> {show? '-' : '+'} </button> <div className="info"> <p>Email: {props.data.email}</p> <p>Company: {props.data.company}</p> <p>Skill: {props.data.skill}</p> <p>Average Grade: {gradesAverage(props.data.grades)}%</p> {show && ( <div> {props.data.grades.map((score, idx) => ( <p key={idx}>Test {idx+1}: {score}%</p> ))} </div> )} {/* 传递初始标签和更新函数 */} <TagsInput initialTags={props.data.tags} setTagsinput={props.updateTags} /> </div> </div> </div> ); } export default Student;
内容的提问来源于stack exchange,提问作者user20271619
相关产品推荐
相关产品推荐

