我正在向axios请求并接收一些数据,然后将它们设置为组件的状态:
componentDidMount() {
instance
.get("https://bartering-application.firebaseio.com/myitems.json")
.then(response => {
var obj = Object.values(response.data);
console.log("parsed", obj);
this.setState({ addedItem: obj });
})
.catch(error => {
console.log(error);
});
}
所以我的状态(具有状态属性addItem)现在将objs作为值。
然后,在我的render()
方法中,我渲染一个子组件,该子组件从我的状态(其属性通过componentDidMount更新)接收道具:
render() {
const items = this.state.addedItem.map(item => {
return (
<MyItem
title={item.Title}
description={item.Description}
condition={item.Condition}
url={item.URL}
/>
)
})
}
这正常工作,但是只有重新加载浏览器后,我才能看到显示的子组件的结果。每当状态属性(在我的情况下,为addItem)更改时,如何使应用自动重新加载?当state属性更改时,应立即使用哪种生命周期方法立即重新渲染DOM?
完整的组件代码如下:
class MyItems extends Component {
constructor(props) {
super(props);
const initial_state = {
image: null,
url: "",
uploadStatus: false,
itemTitle: "",
itemDescription: "",
barteringCondition: "",
addedItem: []
};
this.state = initial_state;
this.handleChange = this.handleChange.bind(this);
this.handleUpload = this.handleUpload.bind(this);
}
componentDidMount() {
instance
.get("https://bartering-application.firebaseio.com/myitems.json")
.then(response => {
var obj = Object.values(response.data);
console.log("parsed", obj);
this.setState({ addedItem: obj });
})
.catch(error => {
console.log(error);
});
}
// componentDidUpdate(prevState){
// if (prevState !== this.state){
// window.location.reload();
// }
// }
handleChange = e => {
if (e.target.files[0]) {
const image = e.target.files[0];
this.setState(
() => ({ image, uploadStatus: true }),
() => console.log(this.state.image.name)
);
}
};
handleUpload = () => {
if (!this.state.uploadStatus) {
alert("No item image was uploaded.");
return null;
}
const { image } = this.state;
const uploadTask = storage.ref(`images/${image.name}`).put(image);
uploadTask.on(
"state_changed",
snapshot => {
// demonstrate the image upload progress
},
error => {
// error function
console.log(error);
},
() => {
//complete function
storage
.ref(`images`)
.child(image.name)
.getDownloadURL()
.then(url => {
console.log(url);
alert("uploaded!");
this.setState({ url });
// When uploadded image url is received, collect all item data into myNewItem object and post this record to Firebase Database
const myNewItem = {
Title: this.state.itemTitle,
Description: this.state.itemDescription,
URL: this.state.url,
Condition: this.state.barteringCondition
};
instance.post("/myitems.json", myNewItem).then(error => {
console.log(error);
});
});
}
);
};
titleChangeHandler = event => {
this.setState({ itemTitle: event.target.value });
};
descriptionChangeHandler = event => {
this.setState({ itemDescription: event.target.value });
};
render() {
const items = this.state.addedItem.map(item => {
return (
<MyItem
title={item.Title}
description={item.Description}
condition={item.Condition}
url={item.URL}
/>
);
});
return (
<Auxiliary>
<div className={classes.MyItems}>
<div className={classes.container}>
<div className={classes.MyItems__left__container}>
<div className={classes.Items__Upload}>
{" "}
<p>Upload your barter item picture below:</p>
<br />
<input type="file" onChange={this.handleChange} />
<br />
<p style={{ padding: "0px", margin: "10px" }}>
Title of the item:
</p>
<input type="text" onChange={this.titleChangeHandler} />
</div>
<div className={classes.Items__Info}>
<div className={classes.Items_Description}>
<p>Describe your item:</p>
<textarea
rows="15"
cols="30"
onChange={this.descriptionChangeHandler}
/>
</div>
<div className={classes.Items_Bartering__Condition}>
<p>Bartering condition:</p>
<br />
<div className={classes.Items__Bartering_Condition_Options}>
<fieldset id="barter-options">
<input type="radio" name="with-similar" />
With a similar item <br />
<input type="radio" name="with-similar-with-extra" />
With a similar item with extra payment <br />
<input type="radio" name="with" />
With
<input
style={{ height: "11px", maxWidth: "240px" }}
type="text"
name="special-item"
placeholder="e.g. Rolex Watch model 16233"
/>
<br />
<input type="radio" name="as-gift" />I give this item as
gift! <br />
<input type="radio" name="as-gift" />I give this item as
gift to
<input
style={{ height: "11px", maxWidth: "120px" }}
type="text"
placeholder="e.g. students"
/>
<br />
</fieldset>
<div className={classes.Items_addButton}>
<button onClick={this.handleUpload}>+ADD</button>
</div>
</div>
</div>
</div>
</div>
<div className={classes.MyItems__right__container}>
<div className={classes.MyItems__right__container__header}>
<p>My items</p>
</div>
<div className={classes.MyItems__right__container__block}>
{/* <MyItem title={this.state.itemTitle} description={this.state.itemDescription} condition={this.state.barteringCondition} url={this.state.url} /> */}
{items}
</div>
</div>
</div>
</div>
</Auxiliary>
);
}
}
export default MyItems;
子MyItem组件:
import React, { useEffect } from "react";
import Auxiliary from "../hoc/Auxiliary";
import { storage } from "../Firebase/Fire";
import classes from "../MyItem/MyItem.module.css";
const MyItem = props => {
return (
<Auxiliary>
<div className={classes.MyItem}>
<h4>Item: {props.title}</h4>
<img
src={props.url || "https://via.placeholder.com/140x100"}
height="100"
width="140"
/>
<p>Description: {props.description}</p>
<p>Bartering condition: {props.condition}</p>
</div>
</Auxiliary>
);
};
export default MyItem;
答案 0 :(得分:0)
Firebase将以对象形式给您响应。 我们需要将其转换为数组并使用它。 在渲染功能开始时尝试以下逻辑,这可能会对您有所帮助。
const fetchedItems = [];
for(let key in this.state.addedItem) {
fetchedItems.push({
...this.state.addedItem[key],
id: key
});
}
const items = fetchedItems.map(item => {
return (
<MyItem
title={item.Title}
description={item.Description}
condition={item.Condition}
url={item.URL}
/>
);
});
答案 1 :(得分:0)
我通过添加window.location.reload()方法解决了此问题,该方法在用户图像成功上传到FIrebase数据库后立即触发DOM的重新呈现。所以这是代码:
instance.post('/myitems.json', myNewItem)
.then(response => {window.location.reload();} )
.then(error => {
console.log(error);
})