Самый надежный способ установить состояние в React JS - PullRequest
1 голос
/ 06 апреля 2020

У меня есть база данных Firebase в реальном времени, база данных JSON, но не sql, у меня есть 5 полей в этой базе данных, в которых они хранятся:

field 1: STRING
field 2: STRING
field 3: STRING
field 4: STRING
field 5: ARRAY OF OBJECTS

, так что база данных с реальным примером выглядит примерно так this:

name: STRING
age: NUMBER
email: STRING
phoneNumber: STRING
skills: OBJECT[]

Теперь я загружаю всю эту информацию из базы данных в виде единственной переменной (var) с именем snapshot.val(). и затем обновлять все состояния, используя setState сразу, как это:

this.setState({
  state_name: snapshot.val().name,
  state_age: snapshot.val().age,
  state_email: snapshot.val().email,
  state_phoneNumber: snapshot.val().phoneNumber,
  state_skills: snapshot.val().skills
});

теперь этот оператор работает нормально, если все значения есть в базе данных, и он также работает нормально, если нет строк в базе данных, но он сталкивается с ошибкой, если поле навыков undefined в базе данных.

Так что setState не выдает ошибку, когда строки не определены, но выдает ошибку, когда массивы не определены. это случилось даже с простым строковым массивом. Теперь, если одно поле не существует и выдается ошибка, весь setState завершается сбоем, поэтому в итоге, если несколько состояний обновляются одновременно и одно из состояний обновляется с ошибкой или исключением, все обновления завершаются неудачно и я обновлял такие деликатные данные с помощью отдельных операторов setState, обновляя только одно состояние в своем собственном блоке try catch. Поэтому, чтобы обновить несколько состояний, которые могут обработать sh, я использую несколько блоков try catch. что-то вроде этого:

try {
  this.setState({
    ownerNameValue: snapshot.val().owner_name,
  });
} catch {}

try {
  this.setState({
    phoneNumberValue: snapshot.val().phone_number,
  });
} catch {}

try {
  this.setState({
    specialityValue: snapshot.val().specialty,
  });
} catch {}

try {
  if (snapshot.val().services != undefined) {
    this.setState({
      selectedOptionSerivce: snapshot.val().services,
    });
  }
} catch {}

try {
  if (snapshot.val().home_service != undefined) {
    this.setState({
      selectedOption: snapshot.val().home_service,
    });
  }
} catch {}

Теперь есть ли более надежный и эффективный способ добиться этого?

Каким-то образом можно обновить все состояния одновременно, а не cra sh, если один из состояние имеет значение как неопределенное или просто терпит неудачу. Таким образом, состояния, которые не сталкиваются с проблемами, обновляются, но состояния, которые сталкиваются с исключениями и ошибками, просто отбрасываются без каких-либо ошибок.

, поэтому это будет что-то вроде этого:

field 1: STRING ->> state updated
field 2: STRING ->> state updated
field 3: STRING ->> state updated
field 4: STRING ->> state updated
field 5: undefined ->> state update FAILED (an array of objects was excepted)

ВНИМАНИЕ: этот вопрос не ограничивается базой данных о пожарных процессах, а setState обрабатывает исключения и ошибки всех видов.

Ответы [ 3 ]

2 голосов
/ 06 апреля 2020

Вы можете назначить навыкам пустой массив, когда он не определен, например:

this.setState({
  state_name: snapshot.val().name,
  state_age: snapshot.val().age,
  state_email: snapshot.val().email,
  state_phoneNumber: snapshot.val().phoneNumber,
  state_skills: snapshot.val().skills || [],
});
1 голос
/ 06 апреля 2020

Во-первых, вам не нужно помещать this.setState внутрь try/catch. setState не выдаст ошибку, если вы попытаетесь установить какое-либо свойство вашего состояния на undefined - это определенно разрешено.

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { foo: "bar" };
  }

  componentDidMount() {
    setTimeout(() => {
      this.setState({
        foo: undefined
      });
    }, 4000);
  }

  render() {
    return this.state.foo !== undefined ? (
      <h1>this.state.foo is not undefined</h1>
    ) : (
      <h1>this.state.foo IS undefined</h1>
    );
  }
}

ReactDOM.render(
  <App />,
  document.getElementById("app")
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>

Итак, когда вы говорите, что это «не получается», потому что вы установили кусок state на undefined, вы, скорее всего, не справитесь с этим дело в другом месте в вашем коде. Это часто случается, когда вы ожидаете, что что-то будет array, и вы пытаетесь использовать метод map, но оказывается, что это undefined.

render() {
  // this.state.skills is `undefined
  // and you're trying to use the `map` method
  // which will fail
  return (
    <div>
      {this.state.skills.map(...)}
    </div>
  )
}

Что вам следует сделать, чтобы указать запасные для элементов, которые возвращаются как undefined:

class App extends React.Component {
  updateState = () => {
    firebase()
      .then(snapshot => {
        this.setState({
          state_name: snapshot.val().name ||  '',
          state_age: snapshot.val().age || 0,
          state_email: snapshot.val().email || '',
          state_phoneNumber: snapshot.val().phoneNumber || '',
          state_skills: snapshot.val().skills || []
        })
      })
      .catch(/* handle errors appropriately */)
  }
}
1 голос
/ 06 апреля 2020

Нет абсолютно никакого смысла делать что-то вроде:

  try {
    if (snapshot.val().home_service != undefined) {
      this.setState({
        selectedOption: snapshot.val().home_service
      });
    }
  } catch{ }

Вызов setState не вызовет sh, если вы установите undefined в качестве значения. Единственный случай, когда вы можете столкнуться с ошибкой, это когда вы случайно забыли проверить это значение внутри методов жизненного цикла или render:

render() {
  return this.state.skills.map(...)
}

Здесь, если skills равно undefined, вы получите ошибка. Ради эффективности вы можете сделать что-то вроде:

class Some {
  constructor() {
    this.state = {...}
  }

  get skills() {
    return this.state.skills || []
  }

  render() {
    return this.skills.map(...)
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...