嗨,我正在尝试在子组件中实现搜索,父组件将从服务器获取数据并将该数据传递给子组件
作为道具,现在子组件必须实现对该数据的搜索,我使用了componentwillreceiveprops
,它已过时如何实现
这不使用componentwillreceiveprops
,下面是我的代码
class Parent extends React.Component{
constructor(props) {
super(props);
this.state = {
data: []
}
}
componentDidMount() {
// mimic api call
const data = [
{ key: 'react'}, { key: 'redux'},
{ key: 'javascript' }, { key: 'Ruby'} ,{key: 'angular'}
]
setTimeout(this.setState({data}), 3000);
}
render() {
return (
<React.Fragment>
<ChildComponent data = {this.state.data}/>
</React.Fragment>
)
}
}
class ChildComponent extends React.Component{
constructor(props) {
super(props);
this.state = {
data: []
}
}
componentwillreceiveprops(nextProps){
this.setState({data: nextProps.data})
}
search(e){
console.log('props,', e.target.value)
let searchedData = this.props.data.filter(el => {
return el.key.startsWith(e.target.value)
})
this.setState({data: searchedData})
};
render(){
return(
<div>
search for (react, redux, angular, ruby)
<br/> <br/> <br/>
<input type = 'text' onChange={this.search.bind(this)}/>
{this.state.data.map(d => {
return (<div key={d.key}>{d.key}</div>)
})}
</div>
)
}
}
答案 0 :(得分:2)
getDerivedStateFromProps
不能直接替代componentWillReceiveProps
。它只是为了响应任何更新而更新状态,与componentWillReceiveProps
不同,getDerivedStateFromProps在子项或父项的每次更新时都被触发,因此您不能简单地在没有任何条件检查的情况下更新状态。为了在道具更改时更新状态,您还需要将先前的道具也存储在child状态下,或者更新child的密钥,以便触发重新渲染
有两种可能的方法。以下是使用getDerivedStateFromProps
import React from "react";
import ReactDOM from "react-dom";
import _ from "lodash";
import "./styles.css";
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {
data: []
};
}
componentDidMount() {
// mimic api call
const data = [
{ key: "react" },
{ key: "redux" },
{ key: "javascript" },
{ key: "Ruby" },
{ key: "angular" }
];
setTimeout(() => {
this.setState({ data });
setTimeout(() => {
this.setState(prev => ({ data: [...prev.data, { key: "Golang" }] }));
}, 3000);
}, 3000);
}
render() {
return (
<React.Fragment>
<ChildComponent data={this.state.data} />
</React.Fragment>
);
}
}
class ChildComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
data: []
};
}
static getDerivedStateFromProps(props, state) {
if (!_.isEqual(props.data, state.prevData)) {
return {
data: props.data,
prevData: state.data
};
} else {
return {
prevData: props.data
};
}
}
search(e) {
console.log("props,", e.target.value);
let searchedData = this.props.data.filter(el => {
return el.key.startsWith(e.target.value);
});
this.setState({ data: searchedData });
}
render() {
return (
<div>
search for (react, redux, angular, ruby)
<br /> <br /> <br />
<input type="text" onChange={this.search.bind(this)} />
{this.state.data.map(d => {
return <div key={d.key}>{d.key}</div>;
})}
</div>
);
}
}
function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Parent />, rootElement);
第二种方法涉及更改子组件的键,而不是实现getDerivedStateFromProps
import React from "react";
import ReactDOM from "react-dom";
import _ from "lodash";
import "./styles.css";
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
keyData: 0
};
}
componentDidMount() {
// mimic api call
const data = [
{ key: "react" },
{ key: "redux" },
{ key: "javascript" },
{ key: "Ruby" },
{ key: "angular" }
];
setTimeout(() => {
this.setState(prev => ({ data, keyData: (prev.keyData + 1) % 10 }));
setTimeout(() => {
this.setState(prev => ({
data: [...prev.data, { key: "Golang" }],
keyData: (prev.keyData + 1) % 10
}));
}, 3000);
}, 3000);
}
render() {
return (
<React.Fragment>
<ChildComponent data={this.state.data} key={this.state.keyData} />
</React.Fragment>
);
}
}
class ChildComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
data: props.data
};
}
search(e) {
console.log("props,", e.target.value);
let searchedData = this.props.data.filter(el => {
return el.key.startsWith(e.target.value);
});
this.setState({ data: searchedData });
}
render() {
return (
<div>
search for (react, redux, angular, ruby)
<br /> <br /> <br />
<input type="text" onChange={this.search.bind(this)} />
{this.state.data.map(d => {
return <div key={d.key}>{d.key}</div>;
})}
</div>
);
}
}
function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Parent />, rootElement);
当您知道子组件中会有相当多的更新,而来自父组件的更新将不那么频繁并且您必须比较getDerivedStateFromProps
的道具被嵌套时,可以继续使用第二种方法。在这种情况下,实现getDerivedStateFromProps
的性能将不如更新密钥,因为您将需要在每个渲染器上执行昂贵的计算。
答案 1 :(得分:0)
要使用新的componentWillReceiveProps()
方法来实现您的getDerivedStateFromProps()
行为,可以使用以下方法替换当前的componentwillreceiveprops()
钩子:
static getDerivedStateFromProps(nextProps, state){
/* Return the new state object that should result from nextProps */
return { data : nextProps.data }
}
getDerivedStateFromProps()
将在呈现组件之前被调用,如果返回非null值,则该返回值将成为组件的状态。
在您的情况下,<ChildComponent>
组件的状态只有一个data
字段,该字段直接从props填充,因此返回{ data : nextProps.data }
就足以更新{{1} }状态字段以匹配传入的data
道具。
通常的想法是,您可以使用此方法根据更改/传入的道具来更新组件的状态。
See this documentation有关data
的更多信息-希望能对您有所帮助!
另外要注意的是,似乎getDerivedStateFromProps()
通过<Parent>
方法更新状态的方式不正确。您应该更新它,如下所示:
setTimeout