【发布时间】:2021-03-12 18:36:38
【问题描述】:
如何将SearchFilter 的值与FilterGrid 同步,以便过滤数据(参见下面的代码)?我在输入时遇到了字段清除值的问题。我使用状态挂钩的方式一定有问题。
问题可能归因于我在位于SearchFilter 的handleOnChange 函数内部调用onChange 的方式。我将onChange“listener”作为属性传递给过滤器,以便我可以访问过滤器之外的值。
不确定这是否不是正确的方法,因为将值直接绑定到网格中的搜索字段给了我这个警告:
“警告:组件正在将受控输入更改为不受控。这可能是由于值从已定义更改为未定义引起的,这不应该发生。决定使用受控输入元素还是不受控输入元素组件的生命周期。”
这是一个实时沙盒的链接:
https://codesandbox.io/s/react-material-ui-search-d4073?file=/src/App.jsx
App.jsx
import React, { useEffect, useState } from "react";
import FilterGrid from "./components/FilterGrid";
import jsonData from "./data/data.json";
const fetchData = () => Promise.resolve(jsonData);
const App = () => {
const [data, setData] = useState([]);
useEffect(() => {
fetchData().then((json) => setData(json));
}, []);
const columns = [
{ key: "nameField", field: "name", title: "Name" },
{ key: "ageField", field: "age", title: "Age" }
];
return <FilterGrid data={data} columns={columns} />;
};
export default App;
FilterGrid.jsx
import React, { useState } from "react";
import SearchFilter from "./SearchFilter";
import MaterialTable from "material-table";
const FilterGrid = (props) => {
const { data, columns } = props;
const [filterValue, setFilterValue] = useState("");
const handleChange = (value) => {
setFilterValue(value);
console.log("Value changed...");
};
const applyFilter = (records) =>
records.filter((record) =>
Object.values(record).some((value) => `${value}`.includes(filterValue))
);
const toolbar = () => (
<div
style={{
display: "flex",
flex: 1,
flexDirection: "row",
justifyContent: "flex-end"
}}
>
<SearchFilter
listeners={{
onChange: handleChange
}}
/>
</div>
);
console.log("Changed filter:", filterValue);
return (
<div>
<MaterialTable
data={applyFilter(data)}
columns={columns}
components={{
Toolbar: toolbar
}}
options={{
search: false
}}
/>
</div>
);
};
export default FilterGrid;
SearchFilter.jsx
import { FormControl, Input } from "@material-ui/core";
import React, { useState } from "react";
import PropTypes from "prop-types";
const SearchFilter = (props) => {
const {
listeners: { onChange }
} = props;
const [internalValue, setInternalValue] = useState("");
const handleOnChange = (e) => {
setInternalValue(e.target.value);
onChange(internalValue);
};
return (
<FormControl>
<Input
type="search"
placeholder="Search..."
onChange={(e) => handleOnChange(e)}
value={internalValue}
/>
</FormControl>
);
};
export default SearchFilter;
data.json
[
{ "name": "Bill", "age": 21 },
{ "name": "Bob", "age": 31 },
{ "name": "Brad", "age": 41 }
]
package.json
{
"dependencies": {
"@material-ui/core": "4.11.1",
"material-table": "1.69.2",
"prop-types": "15.7.2",
"react": "17.0.0",
"react-dom": "17.0.0"
}
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>React Material UI Search</title>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/icon?family=Material+Icons"
/>
</head>
<body>
<div id="root"></div>
</body>
</html>
【问题讨论】:
标签: javascript reactjs data-binding