Перехватчики useState для опубликованного / неопубликованного обратного вызова API - PullRequest
0 голосов
/ 28 февраля 2020

У меня есть пользовательский интерфейс, который может публиковать sh или отменять публикацию sh статьи. Я использую перехватчики реагирования, но не могу найти решение для обновления представления обратного вызова APi.

SectionData возвращает из API массив объектов:

0: {id: "85fdd6e0-3e38-4e42-859b-638c5770d42b", type: "section", attributes: {…}}
1: {id: "88f329dc-457c-4ec2-9c41-7b847f2c9ecb", type: "section", attributes: {…}}
2: {id: "2be4859d-79e1-429f-895f-a725f02f4912", type: "section", attributes: {…}}
3: {id: "a832aa86-9d5c-44a4-b35d-f6a8127ce203", type: "section", attributes: {…}}

В приведенном ниже коде Я пытаюсь использовать useState, чтобы сохранить порядковый номер объекта, по которому щелкнули (который я должен изменить статус с A на B (опубликован / неопубликован или наоборот)

// ListSections. js

const ListSections = ({ sectionData }) => {
  const [rowsData, setRowsData] = React.useState(sectionData);
  const [indexNumStatus, setIndexNumStatus] = React.useState(0);

  /*
  ** @@
  ** @@ PUBLISHED / UNPUBLISHED
  ** @@
  */
  const renderStatusButton = (status, s_id) => 
    <div onClick={() => handleStatusOnClick(status, s_id)}>
      <Status status={status} />
    </div>

  const handleStatusOnClick = (status, s_id) => {

    const changedStatus = 
      status === STATUS.PUBLISHED 
        ? STATUS.UNPUBLISHED 
        : STATUS.PUBLISHED

    const data = {
      "section": {
        "status": changedStatus  
      }
    }

    return api
      .put(URLS.CHANGE_COURSE_SECTION( course_id, s_id ), data)
      .then(({ data }) => {

        const d = data.data;

        // Maps the array to indetify the index of the updated item
        rowsData.map((r, i) => {
          if(r.id === d.id) {
            // ISSUE HERE **** issue is HERE. 
            // indexNumStatus doesn't return the correct value. Always 0
            // first, then on a second click it returns the correct index.
            // For this reason newArrayList returns the incorrect behaviour.          
            setIndexNumStatus(i); 
          }
        })

        // Inject the updated object in to 
        // the array without creating duplicates
        const newArrayList = Object.assign([...rowsData], {[indexNumStatus]: d});

        setRowsData(newArrayList);

      })
      .catch(({response}) => {
        // catch here
      });
  }

  return (
    <TableContainer component={Paper}>
      <Table className={classes.table} aria-label="simple table">
        <TableHead></TableHead>
        <TableBody>
          {rowsData.map((row, index) => (
            <TableRow key={index}>
              <TableCell align="left">{row.attributes.title}</TableCell>

              <TableCell align="center">
                {row.attributes.status}<br />
                {renderStatusButton(row.attributes.status, row.id)}
              </TableCell>

            </TableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  );
}
export default ListSections;

Читающие онлайн люди предлагают использовать useEffect так же, как componentDidUpdate, но, к сожалению, я не могу использовать его внутри обратного вызова в API.
Если я настрою его вне API, как Я передаю номер индекса? Может быть, есть лучшее решение для этого.

Если вы можете предоставить фрагмент кода для любых предложений, это было бы удивительно.

Спасибо за вашу помощь. Джо

Ответы [ 2 ]

0 голосов
/ 28 февраля 2020

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

Решение :
Я не заметил, что в рендере rowData.map уже есть index.

{rowsData.map((row, index) => (
.....
<TableCell align="center"> 
  {renderStatusButton(row.attributes.status, row.id, index)}
</TableCell>

Так что вместо того, чтобы делать еще один .map внутри моего обратного вызова API и попытаться сохранить номер индекса в indexNumStatus:

BAD:
rowsData.map((r, i) => {
  if(r.id === d.id) {
    setIndexNumStatus(i);
  }
 })

.. Я передаю индекс непосредственно в API и использую его с Object.assign, вот предварительный просмотр:

Object.assign([...rowsData], {[index]: data.data});

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

0 голосов
/ 28 февраля 2020

Если вы установите значение через setIndexNumStatus (i); тогда значение не доступно напрямую в следующей строке. По моему мнению, для этого значения нет необходимости использовать useState.

Почему вы просто пишете что-то вроде этого:

    // Just a normal variable
    let indexNumStatus = 0; // <=====

    // Maps the array to indetify the index of the updated item
    rowsData.map((r, i) => {
      if(r.id === d.id) {        
        indexNumStatus = i; // <=====
      }
    })

А потом:

 // Here you can use your variable directly
 const newArrayList = Object.assign([...rowsData], {[indexNumStatus]: d});
 setRowsData(newArrayList);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...