(ReactJS)即使数据库已更新,项目列表也不会在页面上更新

时间:2018-06-27 19:27:49

标签: javascript reactjs

我有一个使用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>
);
}
}

这些全都放在一个文件中,我只是将它们拆分以使其易于阅读(HTML.js):

function addHTML(description, body, callback) {
addAnHTML(description, body);
}

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

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位于数据库同步的另一个文件中:

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

编辑:所以这是我使用的功能的修改:

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);
}

和我班上经过编辑的添加函数如下:

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()包含我的“内容”父级的所有子级值: https://preview.ibb.co/jetOc8/edit.png

1 个答案:

答案 0 :(得分:0)

我将展示如何使用“添加”功能将数据正确映射到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>
    );
  }
}

这足以成功重新渲染。

另一方面,在列表中为元素建立索引也很有用。这对于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对象的状态)。

您可以将这些读数用于我上面刚刚解释的内容

  1. controlleduncontrolled组件
  2. 在React中处理lists components