Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/450.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript (j)项目列表不';即使数据库已更新,也无法在页面上更新_Javascript_Reactjs - Fatal编程技术网

Javascript (j)项目列表不';即使数据库已更新,也无法在页面上更新

Javascript (j)项目列表不';即使数据库已更新,也无法在页面上更新,javascript,reactjs,Javascript,Reactjs,我有一个单页应用程序,它使用firebase和reactjs/nodejs更新/删除/添加html代码(正文和说明)。这些函数工作正常,数据库中的数据也相应更新。但是,执行任何功能后,列表不会刷新(仅当我手动按F5时)。我希望列表在添加/编辑/删除任何内容时动态更改。我该怎么做? 这是我的密码: HTML.js: const updateByPropertyName = (propertyName, value) => () => ({ [propertyName]: value

我有一个单页应用程序,它使用firebase和reactjs/nodejs更新/删除/添加html代码(正文和说明)。这些函数工作正常,数据库中的数据也相应更新。但是,执行任何功能后,列表不会刷新(仅当我手动按F5时)。我希望列表在添加/编辑/删除任何内容时动态更改。我该怎么做? 这是我的密码:

HTML.js:

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
//...