我正在尝试制作一个漂亮的ApiWrapper组件来填充各种子组件中的数据.从我读过的所有内容来看,这应该有效:https://jsfiddle.net/vinniejames/m1mesp6z/1/
class ApiWrapper extends React.Component {
constructor(props) {
super(props);
this.state = {
response: {
"title": 'nothing fetched yet'
}
};
}
componentDidMount() {
this._makeApiCall(this.props.endpoint);
}
_makeApiCall(endpoint) {
fetch(endpoint).then(function(response) {
this.setState({
response: response
});
}.bind(this))
}
render() {
return <Child data = {
this.state.response
}
/>;
}
}
class Child extends React.Component {
constructor(props) {
super(props);
this.state = {
data: props.data
};
}
render() {
console.log(this.state.data, 'new data');
return ( < span > {
this.state.data.title
} < /span>);
};
}
var element = < ApiWrapper endpoint = "https://jsonplaceholder.typicode.com/posts/1" / > ;
ReactDOM.render(
element,
document.getElementById('container')
);
Run Code Online (Sandbox Code Playgroud)
但由于某种原因,当父状态发生变化时,子组件似乎没有更新.
我在这里错过了什么吗?
Yad*_*ran 167
您的代码有两个问题.
您的子组件的初始状态是从props设置的.
this.state = {
data: props.data
};
Run Code Online (Sandbox Code Playgroud)
引用此SO答案:
将初始状态作为
prop
反模式传递给组件是因为getInitialState
(在我们的情况下是构造函数)方法仅在组件第一次呈现时被调用.从来没有.这意味着,如果重新呈现该组件传递不同的值作为aprop
,则组件将不会相应地做出反应,因为组件将从第一次呈现时保持状态.这很容易出错.
因此,如果您无法避免这种情况,理想的解决方案是使用该方法componentWillReceiveProps
来收听新的道具.
将以下代码添加到子组件将解决Child组件重新呈现的问题.
componentWillReceiveProps(nextProps) {
this.setState({ data: nextProps.data });
}
Run Code Online (Sandbox Code Playgroud)
第二个问题是与fetch
.
_makeApiCall(endpoint) {
fetch(endpoint)
.then((response) => response.json()) // ----> you missed this part
.then((response) => this.setState({ response }));
}
Run Code Online (Sandbox Code Playgroud)
这是一个工作小提琴:https://jsfiddle.net/o8b04mLy/
小智 6
如果上述解决方案仍未解决您的问题,我建议您查看一下如何更改状态,如果您没有返回新对象,那么有时 react 会发现新的前一个状态和更改后的状态没有区别,这是在更改状态时始终传递新对象的好习惯,看到新对象的反应肯定会重新渲染所有需要访问该更改状态的组件。
例如: -
在这里,我将更改我状态中一组对象的一个属性,看看我如何将所有数据分散到一个新对象中。另外,下面的代码对你来说可能有点陌生,它是一个 redux reducer 函数,但别担心它只是一种改变状态的方法。
export const addItemToCart = (cartItems,cartItemToBeAdded) => {
return cartItems.map(item => {
if(item.id===existingItem.id){
++item.quantity;
}
// I can simply return item but instead I spread the item and return a new object
return {...item}
})
}
Run Code Online (Sandbox Code Playgroud)
只要确保您正在使用新对象更改状态,即使您对状态进行了微小的更改,只需将其扩展到新对象中然后返回,这将在所有适当的位置触发渲染。希望这有帮助。如果我在某个地方错了,请告诉我:)
归档时间: |
|
查看次数: |
62039 次 |
最近记录: |