You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React组件内如何实现基于状态的姓名、标签双条件学生数据过滤

核心问题

标签状态仅存储在Profile组件的内部状态中,父组件App无法访问该数据,无法实现跨组件的标签过滤逻辑,需通过状态提升将标签数据放到顶层App组件统一管理。

分步修改方案

1. 改造App.js

初始化学生数据时新增tags字段,新增标签搜索状态、标签更新方法、双条件过滤逻辑:

import { useState, useEffect } from 'react'
import axios from 'axios'
import SearchBar from './SearchBar'
import Profile from './Profile'

function App() {
  const [students, setStudents] = useState([])
  const [filteredStudents, setFilteredStudents] = useState([])
  const [nameSearch, setNameSearch] = useState("")
  // 新增标签搜索状态
  const [tagSearch, setTagSearch] = useState("")

  // 请求数据时给每个学生初始化空tags数组
  useEffect(()=>{
    axios.get('Link to the API')
    .then(res => {
      const result = res.data.students.map(student => ({
        ...student,
        tags: []
      }))
      setStudents(result)
    })
  },[])

  // 新增:更新指定学生的标签数组
  const updateStudentTags = (studentId, newTags) => {
    setStudents(prev => prev.map(student => 
      student.id === studentId ? {...student, tags: newTags} : student
    ))
  }

  // 双条件过滤逻辑:同时匹配姓名、标签
  useEffect(() => {
    const lowerNameQuery = nameSearch.toLowerCase()
    const lowerTagQuery = tagSearch.toLowerCase()
    const searchResult = students.filter(student => {
      // 姓名匹配
      const fullName = `${student.firstName} ${student.lastName}`.toLowerCase()
      const nameMatch = !nameSearch || fullName.includes(lowerNameQuery)
      // 标签匹配
      const tagMatch = !tagSearch || student.tags.some(tag => 
        tag.toLowerCase().includes(lowerTagQuery)
      )
      // 两个条件同时满足才返回
      return nameMatch && tagMatch
    })
    setFilteredStudents(searchResult)
  }, [nameSearch, tagSearch, students])

  return (
    <div>
      <SearchBar
        search={nameSearch}
        onChange={e => setNameSearch(e.target.value)}
        placeholder="按姓名搜索"
      />
      {/* 新增标签搜索框 */}
      <SearchBar
        search={tagSearch}
        onChange={e => setTagSearch(e.target.value)}
        placeholder="按标签搜索"
      />
      {/* 无需再区分搜索框是否为空,统一渲染过滤后的列表即可 */}
      <div>
        {filteredStudents.map(student => (
          <Profile
            key={student.id}
            student={student}
            updateTags={(newTags) => updateStudentTags(student.id, newTags)}
          />
        ))}   
      </div>
    </div>
  )
}
export default App

2. 改造Profile.js

移除内部tags状态,改用父组件传入的tags和更新方法:

import { useState } from 'react'
import Tag from './Tag'

function Profile({ student, updateTags }) {
  // 仅保留标签输入框的临时输入状态,永久标签从props取
  const [tagInput, setTagInput] = useState("")

  function handleKeyPress(e) {
    if(e.key === 'Enter' && tagInput.trim()) {
      // 调用父组件方法更新标签,不直接修改原数组
      updateTags([...student.tags, tagInput.trim()])
      setTagInput("")
    }
  }

  return(
    <div>
      {/* 原有学生信息渲染逻辑保持不变 */}
      <Tag
        onChange={e => setTagInput(e.target.value)}
        onKeyPress={handleKeyPress}
        tags={student.tags}
        tag={tagInput} 
      />
    </div>
  )
}
export default Profile

3. 改造Tag.js(可选优化)

仅新增遍历标签的key属性,避免React告警,原有逻辑无变动:

export default function Tag({tag, tags, onChange, onKeyPress}) {
  return (
    <div>
      {tags.length > 0 &&
        <div>
          {tags.map((tag, index) => (
            <span key={index}>{tag}</span>
          ))}
        </div>
      }       
      <input 
        type='text'
        value={tag}
        placeholder="Add a tag"
        key='tag-input'
        onKeyPress={onKeyPress}
        onChange={onChange}
      />
    </div>
  )
}

内容的提问来源于stack exchange,提问作者SelfTaughtLooking4Job

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 02:36:03