在React.js中根据属性值过滤字符



我正在尝试建立一个基于瑞克和莫蒂api的应用程序。我想按物种过滤字符。我为每个物种值创建了单独的组件例如:Human.js

export const Human = ({ match }) => {
const { species } = match.params;
const [characterFilters, setCharacterFilters] = useState([]);
useEffect(() => {
try {
fetch('https://rickandmortyapi.com/api/character?species=human')
.then((res) => res.json())
.then((res) => setCharacterFilters(res))
.catch((err) => console.log(err));
} catch (e) {
console.log(e);
}
}, []);
const { name, image } = characterFilters;
return (
<div>
<h2>Name: {name}</h2>
<div>
<img alt={name} src={image}></img>
</div>
</div>
);
};

在字符文件中,我已经根据select property selected

设置了条件Characters.js

export const Characters = () => {
const [characters, setCharacters] = useState();
useEffect(() => {
try {
fetch(CHARACTERS_PAGE_URL)
.then((res) => res.json())
.then(({ results }) => {
if (results && Array.isArray(results)) {
setCharacters(results);
}
})
.catch((err) => console.log(err));
} catch (e) {
console.log(e);
}
}, []);
const handleSpeciesChange = (e) => {
console.log("[e.target.value]", e.target.value);
switch (e.target.value) {
case "human":
return <Human />;
break;
case "alien":
return <Alien />;
break;
case "unknown":
return <Unknown />;
break;
default:
return;
}
};
const handleStatusChange = (e) => {
switch (e.target.value) {
case "alive":
return <Human />;
break;
case "dead":
return <Alien />;
break;
case "unknown":
return <Unknown />;
break;
default:
return;
}
};
if (!characters) {
return <Loading />;
}
return (
<div className="p-4 font-mono text-green-500 ">
<div className="flex flex-row">
<div className="m-4 ">
<label>Species</label>
<select name="species" id="species" onChange={handleSpeciesChange}>
<option value="all">all</option>
<option value="human">human</option>
<option value="alien">alien</option>
<option value="unknown">unknown</option>
</select>
</div>
<div className="m-4">
<label>Status</label>
<select name="status" id="status" onChange={handleStatusChange}>
<option value="all">all</option>
<option value="alive">alive</option>
<option value="dead">dead</option>
<option value="unknown">unknown</option>
</select>
</div>
<div className="m-4">
<label>Gender</label>
<select name="gender" id="gender">
<option value="all">all</option>
<option value="female">female</option>
<option value="male">male</option>
<option value="genderless">genderless</option>
<option value="unknown">unknown</option>
</select>
</div>
</div>
<h1 className="text-4xl">Characters</h1>
<Pagination data={characters} pageLimit={5} />
<div className="grid grid-flow-col grid-cols-5 grid-rows-4 gap-4">
{characters.map((character) => (
<div key={character.id}>
<Character character={character} />
</div>
))}
</div>
</div>
);
};

但是我没有得到过滤字符。我是React的新手。请帮助我理解,我在这里做错了什么?是否有可能创建一个通用的过滤器组件,我将能够申请不同的属性过滤器?

不能从回调中返回jsx

使过滤器得到存储,并只呈现这些值从数组:

export const Characters = () => {
const [characters, setCharacters] = useState();
const [ speciesFilter, setSpeciesFilter ] = useState('');
const [ status, setStatus] = useState('');
useEffect(() => {
try {
fetch(CHARACTERS_PAGE_URL)
.then((res) => res.json())
.then(({ results }) => {
if (results && Array.isArray(results)) {
setCharacters(results);
}
})
.catch((err) => console.log(err));
} catch (e) {
console.log(e);
}
}, []);
const handleSpeciesChange = (e) => {
console.log("[e.target.value]", e.target.value);
setSpeciesFilter(e.target.value)
};
const handleStatusChange = (e) => {
setStatus(e.target.value);
};
if (!characters) {
return <Loading />;
}
let filteredCharacters = characters;
if (speciesFilter) {
filteredCharacters = filteredCharacters.filter(c => c.species === speciesFilter);
}
if (status ) {
filteredCharacters = filteredCharacters.filter(c => c.status === status);
}
return (
<div className="p-4 font-mono text-green-500 ">
<div className="flex flex-row">
<div className="m-4 ">
<label>Species</label>
<select name="species" id="species" onChange={handleSpeciesChange}>
<option value="all">all</option>
<option value="human">human</option>
<option value="alien">alien</option>
<option value="unknown">unknown</option>
</select>
</div>
<div className="m-4">
<label>Status</label>
<select name="status" id="status" onChange={handleStatusChange}>
<option value="all">all</option>
<option value="alive">alive</option>
<option value="dead">dead</option>
<option value="unknown">unknown</option>
</select>
</div>
<div className="m-4">
<label>Gender</label>
<select name="gender" id="gender">
<option value="all">all</option>
<option value="female">female</option>
<option value="male">male</option>
<option value="genderless">genderless</option>
<option value="unknown">unknown</option>
</select>
</div>
</div>
<h1 className="text-4xl">Characters</h1>
<Pagination data={characters} pageLimit={5} />
<div className="grid grid-flow-col grid-cols-5 grid-rows-4 gap-4">
{filteredCharacters.map((character) => (
<div key={character.id}>
<Character character={character} />
</div>
))}
</div>
</div>
);
};

上面的例子使用了一个可以改进的过滤器

我这里做错了什么?

从回调中返回JSX,例如,

onChange={handleStatusChange}

这里你传递了一个函数,它将传递事件给你处理,问题是,从这个函数返回一个组件不做任何事情,它不会告诉React渲染你返回的组件。

相反,您可以将该值存储在状态中,并相应地执行一些操作,例如,使用该值 筛选数组。

是否有可能创建一个公共过滤器组件,我是否能够申请不同的属性过滤器?

这可以通过将字符传递给该组件和过滤器值 来实现。
export const FilterCharacters = ({ characters, status, specie }) => {
let filteredCharacters = characters;
if (specie ) {
filteredCharacters = filteredCharacters.filter(c => c.species === specie);
}
if (status ) {
filteredCharacters = filteredCharacters.filter(c => c.status === status);
}
return filteredCharacters.map((character) => (
<div key={character.id}>
<Character character={character} />
</div>
))
}

对于您的Human和特定的物种组件,它调用API来过滤值,但我假设您最初已经获得了所有值,因此您只能从那里过滤,如果不是这种情况,您可以通过传递物种和状态使Human更通用,并使用该值查询API

最新更新