首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >(ReactJS)页面上的项目列表不会更新,即使数据库已更新也是如此

(ReactJS)页面上的项目列表不会更新,即使数据库已更新也是如此
EN

Stack Overflow用户
提问于 2018-06-28 03:27:49
回答 1查看 149关注 0票数 0

我有一个单页面应用程序,它使用firebase和reactjs/nodejs来更新/删除/添加html代码(正文和描述)。这些函数运行良好,数据库中的数据也会相应地更新。但是,一旦我执行任何功能,列表就不会刷新(仅当我手动按F5键时)。当我添加/编辑/删除任何内容时,我希望列表动态更改。我该怎么做呢?下面是我的代码:

HTML.js:

代码语言:javascript
复制
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>
);
}
}

所有这些都在一个文件中,我只是将它们拆分以便于阅读(HTML.js):

代码语言:javascript
复制
function addHTML(description, body, callback) {
addAnHTML(description, body);
}

下面是同一文件中的第二个类,它负责显示项目列表:

代码语言:javascript
复制
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>
);
}
}

函数addAnHTML位于与数据库同步的其他文件中:

代码语言:javascript
复制
export const addAnHTML = (description, body) => {
var html =
{
  description: description,
  body: body,
  created_at: format.asString(),
  updated_at: ""
}
db.ref('Content').push(html);
alert("Content Added");
}

我的页面看起来像这样:https://preview.ibb.co/fTwiaT/Untitled.png

我的数据库看起来像这样(添加到db中,但不是动态添加的):https://image.ibb.co/nNEapo/database.png

编辑:下面是我使用的函数的编辑:

代码语言:javascript
复制
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函数如下所示:

代码语言:javascript
复制
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()包含我的"Content“父级的所有子值:https://preview.ibb.co/jetOc8/edit.png

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-28 05:04:23

我将展示如何正确地将您的数据映射到DOM以实现“添加”功能。

下面是修改后的HTML类

代码语言:javascript
复制
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>
    );
  }
}

这对于成功的重新渲染来说已经足够了。

另外,对列表中的元素进行索引也很有用。对于React来说,高效渲染真的很有用。为此,您可以像这样修改HTMList类:

代码语言:javascript
复制
//...
        <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对象)。

您可以使用这些读数来阅读我刚才解释的内容。

  1. controlled vs uncontrolled components
  2. handling lists components in React
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51070111

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档