Javascript (j)项目列表不';即使数据库已更新,也无法在页面上更新
我有一个单页应用程序,它使用firebase和reactjs/nodejs更新/删除/添加html代码(正文和说明)。这些函数工作正常,数据库中的数据也相应更新。但是,执行任何功能后,列表不会刷新(仅当我手动按F5时)。我希望列表在添加/编辑/删除任何内容时动态更改。我该怎么做? 这是我的密码: HTML.js:Javascript (j)项目列表不';即使数据库已更新,也无法在页面上更新,javascript,reactjs,Javascript,Reactjs,我有一个单页应用程序,它使用firebase和reactjs/nodejs更新/删除/添加html代码(正文和说明)。这些函数工作正常,数据库中的数据也相应更新。但是,执行任何功能后,列表不会刷新(仅当我手动按F5时)。我希望列表在添加/编辑/删除任何内容时动态更改。我该怎么做? 这是我的密码: HTML.js: const updateByPropertyName = (propertyName, value) => () => ({ [propertyName]: value
const updateByPropertyName = (propertyName, value) => () => ({
[propertyName]: value,
});
class HTML extends Component {
constructor(props) {
super(props);
this.state = {
html: []
};
}
componentDidMount() {
db.onceGetHTML().then(snapshot =>
this.setState(() => ({ html: snapshot.val() }))
);
}
render() {
const { html } = this.state;
const { description } = this.state;
const { body } = this.state;
return (
<div>
<h1>Home</h1>
<p>The Home Page is accessible by every signed in user.</p>
<input value={description}
onChange={event => this.setState(updateByPropertyName('description', event.target.value))}
type="text"
placeholder="Description..."
/>
<input value={body}
onChange={event => this.setState(updateByPropertyName('body', event.target.value))}
type="text"
placeholder="Body..."
/>
<button onClick={() => addHTML(description, body)}>Add Content</button>
{!!html && <HTMLList html={html} />}
</div>
);
}
}
这是同一文件中的第二个类,负责显示项目列表:
class HTMLList extends Component {
constructor(props) {
super(props);
this.state = {
BODY: '',
desc: '',
html: ''
};
}
render() {
const { html } = this.props;
const { desc } = this.state;
const { BODY } = this.state;
return (
<div>
<h2>List of HTML available:</h2>
{Object.keys(html).map((key, index) =>
<div>
{index + 1}.
{html[key].description}
<img src="http://www.stilltimecollection.co.uk/images/english/b_delete.gif" onClick={() => deleteHTML(key)} />
<Popup trigger={<img src="https://www.faktorzehn.org/de/wp-content/uploads/sites/2/2015/03/f10-org-new_3_6_0-edit.gif" />
} position="right center">
<div>
<input value={desc}
onChange={event => this.setState(updateByPropertyName('desc', event.target.value))}
type="text"
placeholder="Descripton.."
/>
<input value={BODY}
onChange={event => this.setState(updateByPropertyName('BODY', event.target.value))}
type="text"
placeholder="Body..."
/>
<button onClick={() => updateHTML(key, desc, BODY)}>Update Content</button>
</div>
</Popup>
<br></br>
</div>
)}
</div>
);
}
}
我的页面如下所示:
我的数据库如下所示(在db中添加,但不是动态添加):
编辑:下面是我使用的函数的编辑:
export const onceGetHTML = () =>
db.ref('Content').once('value');
export const addAnHTML = (description, body) => {
console.log(description);
console.log(body);
var html =
{
description: description,
body: body,
created_at: format.asString(),
updated_at: ""
}
db.ref('Content').push(html);
}
我的类中编辑的add函数如下所示:
addContent(description, body) {
this.setState({
html: [
...this.state.html,
{
description: this.state.description,
body: this.state.body
}
]
});
addAnHTML(this.state.description,this.state.body);
}
Snapshot.val()包含我的“内容”父项的所有子值:
我将展示如何正确地将数据映射到DOM以实现“添加”功能 下面是修改后的HTML类
export class HTML extends Component {
constructor(props) {
super(props);
this.state = {
html: [],
// if you keep your user inputted data in the DOM state, it's good to initialize them first, otherwise your component will suddenly change from an uncontrolled component to a controlled component.
description: "",
body: ""
};
}
componentDidMount() {
// EDIT: code here for initializing `html`
db.onceGetHTML().then(snapshot =>
// EDIT: it's simpler to just call setState with the new state object you want
this.setState({ html: snapshot.val()})
);
}
// use class methods to update your DOM state, because inside these methods
// also don't forget to call your API here
addContent(description, body) {
// EDIT: make sure to make your call to the db for adding an entry
this.setState({
// please keep in mind that you should NEVER mutate your state, so in here I'm using the spread operator to create a new array instance
// this is appending a new entry to the old "html"
html: [
...this.state.html,
{
description: this.state.description,
body: this.state.body
}
]
});
}
// use this to update the state for each input field
updateByPropertyName(property, e) {
this.setState({
[property]: e.target.value
});
}
render() {
const { html } = this.state;
const { description } = this.state;
const { body } = this.state;
return (
<div>
<h1>Home</h1>
<p>The Home Page is accessible by every signed in user.</p>
<input
value={description}
onChange={this.updateByPropertyName.bind(this, "description")}
type="text"
placeholder="Description..."
/>
<input
value={body}
onChange={this.updateByPropertyName.bind(this, "body")}
type="text"
placeholder="Body..."
/>
// this onClick event will call "this.setState(...)" which will trigger the re-render (or the "refresh" you are looking for)
<button onClick={this.addContent.bind(this)}>Add Content</button>
{!!html && <HTMLList html={html} />}
</div>
);
}
}
导出类HTML扩展组件{
建造师(道具){
超级(道具);
此.state={
html:[],
//如果您将用户输入的数据保持在DOM状态,最好先初始化它们,否则您的组件将突然从非受控组件变为受控组件。
说明:“,
正文:“”
};
}
componentDidMount(){
//编辑:此处的代码用于初始化`html`
db.onceGetHTML().then(快照=>
//编辑:使用所需的新状态对象调用setState更简单
this.setState({html:snapshot.val()})
);
}
//使用类方法更新DOM状态,因为在这些方法中
//也不要忘记在这里调用API
添加内容(描述,正文){
//编辑:确保您已呼叫数据库以添加条目
这是我的国家({
//请记住,您永远不应该改变您的状态,因此在这里,我将使用spread操作符创建一个新的数组实例
//这是在旧的“html”中添加一个新条目
html:[
…this.state.html,
{
description:this.state.description,
身体:这个。状态。身体
}
]
});
}
//使用此选项可更新每个输入字段的状态
updateByPropertyName(属性,e){
这是我的国家({
[属性]:e.target.value
});
}
render(){
const{html}=this.state;
const{description}=this.state;
const{body}=this.state;
返回(
家
每个登录用户都可以访问主页
//此onClick事件将调用“this.setState(…)”,这将触发重新渲染(或您正在查找的“刷新”)
添加内容
{!!html&&}
);
}
}
这将足以成功地重新渲染
另一方面,为列表中的元素编制索引也很有用。对于React来说,高效渲染非常有用。为此,您可以修改HTMList类,如下所示:
//...
<h2>List of HTML available:</h2>
{Object.keys(html).map((key, index) => (
// using the index parameter supported in the .map callback it's okay
// because it makes your DOM list nodes predictable and easy for React to re-render
<div key={index}>
{index + 1}.
{html[key].description}
<img
//...
/。。。
可用的HTML列表:
{Object.keys(html).map((键,索引)=>(
//使用.map回调中支持的索引参数就可以了
//因为它使DOM列表节点可预测,并且易于重新渲染
{index+1}。
{html[key].description}
这个解决方案还带来了另一个问题。如果我试图使用代码中显示的snapshot.val()来使用已经存在的旧数据(而不是html:description(something)…)它将正确加载数据,但当我尝试添加任何内容时,数据会被新添加的组件覆盖,然后列表会按照我的要求运行,但我还希望显示旧值,而不仅仅是显示添加的值。我如何解决这个问题?我相信我的问题在于const{html}=this.props;在我的HTMLList类中。但我不知道如何修复它。如果您能向我解释一下覆盖发生在哪里?snapshot.val()是否返回对象或数组?我已经更新了一些内容,您能粘贴snapshot.val()的确切值吗是吗?我将更新文章末尾代码中显示的函数,请查看它们。现在更新您可以查看我放置的图片,查看snapshot.val()返回的内容。
export class HTML extends Component {
constructor(props) {
super(props);
this.state = {
html: [],
// if you keep your user inputted data in the DOM state, it's good to initialize them first, otherwise your component will suddenly change from an uncontrolled component to a controlled component.
description: "",
body: ""
};
}
componentDidMount() {
// EDIT: code here for initializing `html`
db.onceGetHTML().then(snapshot =>
// EDIT: it's simpler to just call setState with the new state object you want
this.setState({ html: snapshot.val()})
);
}
// use class methods to update your DOM state, because inside these methods
// also don't forget to call your API here
addContent(description, body) {
// EDIT: make sure to make your call to the db for adding an entry
this.setState({
// please keep in mind that you should NEVER mutate your state, so in here I'm using the spread operator to create a new array instance
// this is appending a new entry to the old "html"
html: [
...this.state.html,
{
description: this.state.description,
body: this.state.body
}
]
});
}
// use this to update the state for each input field
updateByPropertyName(property, e) {
this.setState({
[property]: e.target.value
});
}
render() {
const { html } = this.state;
const { description } = this.state;
const { body } = this.state;
return (
<div>
<h1>Home</h1>
<p>The Home Page is accessible by every signed in user.</p>
<input
value={description}
onChange={this.updateByPropertyName.bind(this, "description")}
type="text"
placeholder="Description..."
/>
<input
value={body}
onChange={this.updateByPropertyName.bind(this, "body")}
type="text"
placeholder="Body..."
/>
// this onClick event will call "this.setState(...)" which will trigger the re-render (or the "refresh" you are looking for)
<button onClick={this.addContent.bind(this)}>Add Content</button>
{!!html && <HTMLList html={html} />}
</div>
);
}
}
//...
<h2>List of HTML available:</h2>
{Object.keys(html).map((key, index) => (
// using the index parameter supported in the .map callback it's okay
// because it makes your DOM list nodes predictable and easy for React to re-render
<div key={index}>
{index + 1}.
{html[key].description}
<img
//...