ReactJs – невозможно прочитать свойство «appendChild» со значением null

Я знаю, что этот вопрос неоднократно публиковался на Stack Overflow. Но я не могу понять, как исправить это в моем коде.

По сути, я создаю простое веб-приложение для пожертвований в ReactJS. Очень простой на данный момент.

1) Есть короткая форма, где вы вводите число (Form.JS). А затем это значение анализируется в ProgressBar.js.

2) Затем я подсчитываю общее количество пожертвований и вставляю это общее количество/счет/сумму на страницу.

Теперь то, что я пытаюсь сделать, это добавить стиль к моему бару. Например, если общее количество пожертвований составляет ‹ 10, добавьте div, красный цвет, ширина: 10 пикселей.

Но я продолжаю получать ошибку, что свойство appendChild равно null. Я думаю, это может быть потому, что мой код работает до того, как сумма будет рассчитана? Я просто не знаю, как это исправить.

Вот оба моих фрагмента кода ниже:

FORM.JS

import React from 'react';
import 'bulma';

const Form = ({ handleSubmit, handleChange}) => {

return (
  <form onSubmit={handleSubmit}>
    <div className="field">
      <label htmlFor="name">Name</label>
      <input className="input"
        type="number"
        placeholder="number"
        name="number"
        onChange={handleChange}
        required
      />
    </div>
    <button className="button is-primary">Give Now</button>
  </form>
  );
};
export default Form;

PROGRESSBAR.JS

import React from 'react';
import 'bulma';

const ProgressBar = ({donated}) => {

  const numbers = donated.map(Number);

  // FUNCTION TO CALCULATE TOTAL DONATIONS
  function add(a, b) {
    return a + b;
  }
  const sum = numbers.reduce(add, 0);

  // IF SUM DONATIONS ARE LESS THAN THE VALUE OF 10, ADD THIS CSS TO THE JSX
  if (sum < 10) {
    const div = document.createElement('div');
    div.style.background = 'red';
    div.style.width = '10px';
    div.style.height = '50px';
    div.style.float = 'left';
    document.querySelector('.bar').appendChild(div);
 }
// JSX
  return (
    <div>
      <p>donations made so far: {donated.length}</p>
      <p>£{sum}</p>
      <div className="bar"></div>
      <ul>
       {donated.map((donated, i) => <li key={i}>{donated}</li>)}
     </ul>
  </div>
 );
};
export default ProgressBar;

APP.JS

class App extends React.Component {

 constructor() {
  super();

  this.state = {
   number: '',
   donated: []
 };

 this.handleChange = this.handleChange.bind(this);
 this.handleSubmit = this.handleSubmit.bind(this);
 // we need to bind otherwise this is undefined
}

//HANDLE FUNCTIONS
handleChange(e) {
this.setState({ number: e.target.value }, () => 
console.log(this.state.number));
 }

handleSubmit(e) {
e.preventDefault();
this.setState({donated: this.state.donated.concat(this.state.number)});
}

render() {
return (
  <main>
    <section className="section">
      <h1 className="is-size-2">DONATE FOR A GOOD CAUSE</h1>
      <ProgressBar donated={this.state.donated} />
      <Form handleChange={this.handleChange} handleSubmit={this.handleSubmit} />
    </section>
  </main>
 );
 }
}
ReactDOM.render(
<App />,
document.getElementById('root')

);


person Reena Verma    schedule 26.05.2018    source источник


Ответы (1)


Ваш код запускается до создания узлов, поэтому он не может ими манипулировать. Но обычно вам не нужно выполнять такие манипуляции с DOM в React. Просто поместите логику в свой JSX, например:

<div className="bar">
    {sum < 10 && (
        <div style={{background: 'red'}} />
    )}
</div>
person JW.    schedule 26.05.2018
comment
ок, спасибо.... не сработало... :/ . Что я пытаюсь сделать, так это добавлять блок каждый раз, когда отправляется пожертвование... - person Reena Verma; 27.05.2018
comment
Из вашего кода непонятно, как связаны эти два компонента. Но что вам, вероятно, следует сделать, так это отслеживать количество пожертвований в переменной состояния, передавать его в свой компонент прогресса в качестве свойства и повторять это количество раз в JSX, отображая блок для каждого. - person JW.; 27.05.2018
comment
хорошо, у меня это работает... я в основном просто перебираю массив пожертвований... но я не делаю этого в JSX... это плохая практика? for (var i = 0; i ‹ number.length; i++) { if (i ‹ 10) { const div = document.createElement('div'); div.style.background = 'красный'; div.style.width = '50px'; div.style.height = '50px'; div.style.float = 'левый'; document.querySelector('.bar').appendChild(div); } } - person Reena Verma; 27.05.2018
comment
Да, вы вряд ли вообще должны делать какие-либо манипуляции с DOM с React. В этом-то и дело. Вы можете сделать что-то вроде этого. - person JW.; 27.05.2018
comment
Итак, я передаю количество пожертвований. Это передается в качестве пожертвований. Из-за того, что мой компонент является простым функциональным компонентом, я не думаю, что смогу использовать состояние, верно? Спасибо. - person Reena Verma; 27.05.2018