假设我在组件内部有一个模态,并且想在单击某些按钮时显示模态:
render(){
...
<Modal
is={this.state.productId}
visilble={this.state.visible}
/>
}
在模态组件内部,我想调用API以基于选定的ID获取产品详细信息,如下所示:
componentWillReceiveProps(nextProps) {
if(nextProps.visible && !this.props.visible) {
fetch(...).then(res => {
this.setState({
product: res.data
})
}).catch(err => {
...
})
}
}
在React docs中说,不赞成componentWillReceiveProps,componentWillUpdate,您应该在新代码中避免使用它们。因此,我尝试使用静态getDerivedStateFromProps()
static getDerivedStateFromProps()(nextProps) {
if(nextProps.visible && ...) {
fetch(...).then(res => {
return {
product: res.data
}
}).catch(err => {
...
})
} else return null (or just return null here without else)
}
上面的代码不起作用,因为fetch是异步的,因此它总是返回null或不返回任何东西,您不能在这里使用await来等待api也解决,而且我听说getDerivedStateFromProps不应该用于数据提取。
那么解决问题的最佳方法是什么?
答案 0 :(得分:0)
我认为最好决定是否在父组件中显示Modal组件,因为Modal组件应该是仅呈现与模态相关的视图的功能组件。这样,每次Modal组件都不会被渲染,只有在visible标志为true时才会被渲染。
{ this.state.visible &&
<Modal />
}
在父组件中,如果仅在需要初始渲染后才需要获取数据,则可以在componentDidMount中获取数据;如果在每次更新后需要模态获取数据,则可以在componentDidUpdate中获取数据。提取数据集后,可见状态为true。
快乐编码!
答案 1 :(得分:0)
您可以基于Modal
来安装this.state.visible
并在componentDidMount上安装Modal
或通过componentDidUpdate改变道具时开始获取。
// delay
const delay = () => new Promise(res => setTimeout(res, 1000));
// fake products
const products = [
{ id: 1, text: "product 1" },
{ id: 2, text: "product 2" },
{ id: 3, text: "product 3" }
];
// fake ajax call
const API = async productId => {
await delay();
return products.find(p => p.id === productId);
};
class Parent extends Component {
state = { productId: 1, visible: false };
toggleShow = () => {
this.setState(prevState => ({ visible: !prevState.visible }));
};
setProductId = productId => this.setState({ productId, visible: true });
render() {
return (
<div className="App">
<button onClick={this.toggleShow}>show or hide</button>
<button onClick={() => this.setProductId(1)}>fetch product 1</button>
<button onClick={() => this.setProductId(2)}>fetch product 2</button>
<button onClick={() => this.setProductId(3)}>fetch product 3</button>
<button onClick={() => this.setProductId(4)}>unknown product id</button>
{this.state.visible && <Modal is={this.state.productId} />}
</div>
);
}
}
class Modal extends Component {
state = { product: null, fetching: false };
componentDidMount = () => {
this.fetchProduct();
};
componentDidUpdate = prevProps => {
if (prevProps.is !== this.props.is) {
this.fetchProduct();
}
};
fetchProduct = async () => {
this.setState({ fetching: true });
const product = await API(this.props.is);
this.setState({ product, fetching: false });
};
render() {
const { product, fetching } = this.state;
if (fetching) return <h1>{`fetching product ${this.props.is}`}</h1>;
return product ? (
<div>
<h1>{`product id: ${product.id}`}</h1>
<h3>{`text: ${product.text}`}</h3>
</div>
) : (
<h1>Product not found</h1>
);
}
}
答案 2 :(得分:0)
实际上,您可以在另一种 pureComponent 中使用<modal/>
(例如:componentContainer
),只需在主视图中调用它即可。并仅在主视图状态内使用一个对象作为<componentContainer/>
数据作用域,并将其作为此代码的属性提供
construcor(prop){
super(props);
this.state={
productDetail:null<<change this in data fetch
}
}
<componentContainer data={this.state.productDetail} modalVisible={this.state.changeNumderModal}/>
并在组件容器内:
<Modal
animationType="fade"
transparent={true}
visible={this.props.modalVisible}//<<<<<<<<<
onRequestClose={() => {
}}>
//contents:
this.props.data.map(()=>//-----)
</View>
</Modal>
在这种方法中,您只有一个模式和一个作用域作为其数据,您可以在主组件中调用 fetch 和其他函数,其他函数也可以...如果需要,您可以甚至将功能属性传递给模式容器:
someFunction(someval){
//do some thing
}
<componentContainer data={this.state.productDetail} modalVisible={this.state.changeNumderModal} someFunction={(val)=>this.someFunction(val)}/>
并在 中调用它:
this.props.someFunction('what ever you want')
答案 3 :(得分:0)
所以让我们假设您已经通过单击按钮完成了模态的隐藏和显示,现在只要打开模型 在componentWillMount函数内部
class Modal extends Component {
this.state = {product:[], loader : false}
componentWillMount(){
fetch(...).then(res => {
this.setState({
product: res.data
})
}).catch(err => {
...
})
}
render(){
const {product, loader} = this.state;
return (
if (loader) return <ProductComponent data = {product}/>
else return <div> No data found </div>
);
}
}
答案 4 :(得分:0)
您可以使用以下方法:
componentDidUpdate(prevProps, prevState, snapshot) {
if (this.props.visible && !prevProps.visible) {
// make the API call here
}
}