работает в компоненте класса, но в хуках функция val () вызывает бесконечность раз - PullRequest
1 голос
/ 29 марта 2020
function Inhook(props) {
  const initialState = 0;
  const [records, setRecords] = useState([]);
  const [count, setCount] = useState(initialState);
  const [show, setShow] = useState(false);
  const [store, setStore] = useState(initialState);
  const [store1, setStore1] = useState(initialState);
  setRecords(props.records);

  function val(e) {
    debugger;
    console.log("hhh", e);
    setStore(e);
    if (store === store1) {
      if (count == 0) {
        setShow(true);
      } else {
        setShow(false);
      }
    } else {
      setShow(true);
      setCount(0);
    }
    setCount(count + 1);
    // console.log(count,'counttt');

    setStore1(e);
  }
  return (
    <div>
      <React.Fragment>
        <br />
        <div className="Tree">
          <h1 style={{ textAlign: "center" }}>Employee Tree</h1>
          <h3>Test Case 1</h3>
          <h4>Employee Tree</h4>
          {
            (records.sort((x, y) => (x.empName.toLowerCase() > y.empName.toLowerCase()) * 2 - 1),
            records.map(empId => {
              return empId.managerId === 0 ? (
                <ul key={empId.id}>
                  <li style={{ fontWeight: "Bold" }}>
                    {empId.empName.toLowerCase()}
                    <p>Employees of : {empId.empName.toLowerCase()}</p>
                    <ul>
                      {records.map(s =>
                        s.managerId === empId.id ? (
                          <li type="square" key={s.id}>
                            {s.empName.toLowerCase()}
                            {empId.managerId === s.id ? <p>Employees of :{s.empName.toLowerCase()}</p> : <p></p>}
                            {records.map(e =>
                              e.managerId === s.id ? (
                                <div>
                                  {e.managerId === s.id ? <p>{val(s.id)}</p> : <p></p>}
                                  {show ? <p>Employees of :{s.empName.toLowerCase()}</p> : <p></p>}
                                  <li key={e.id} type="disc" style={{ marginLeft: "120px" }}>
                                    {e.empName.toLowerCase()}
                                  </li>
                                </div>
                              ) : (
                                ""
                              )
                            )}
                          </li>
                        ) : (
                          ""
                        )
                      )}
                    </ul>
                  </li>
                </ul>
              ) : (
                ""
              );
            }))
          }
        </div>
      </React.Fragment>
    </div>
  );
}
export default Inhook;

Я получил данные записей из json, которые имеют имя, идентификатор, идентификатор менеджера и зарплату и так далее. когда я делал это в компоненте класса, он работал, получал выходные данные, в функции или хуках функция val () в jsx, вызывающая бесконечность, получала ошибку вроде (Ошибка: слишком много повторных визуализаций. React ограничивает число визуализаций, чтобы предотвратить бесконечный l oop.)

Ответы [ 2 ]

0 голосов
/ 29 марта 2020

Вам необходимо удалить эту строку setRecords(props.records), потому что она вызывает изменение состояния на каждом рендере, который равен бесконечному l oop, который у вас есть.
Более того, вам также не нужна эта строка const [records, setRecords] = useState([]); и вы можете просто отображать записи, которые у вас есть в подпорках, здесь нет необходимости в местном состоянии.

Более того, некоторые советы:

  • Кажется, вы пытаетесь построить и отобразить Дерево сотрудников в то же время, что очень сложно, вы должны построить данные, которые необходимо отобразить, прежде чем отобразить его. Чтобы построить дерево из массива, посмотрите этот ответ stackoverflow

Это будет выглядеть так:


function Inhook(props) {
    const initialState = 0;
    const records = props.records

    const sortedRecords = records.sort((x, y) => (x.empName.toLowerCase() > y.empName.toLowerCase()) * 2 - 1)
    const employeeTree = createEmployeeTree(sortedRecords)

    return (
        <div>
            <React.Fragment>
                <br />
                <div className="Tree">
                    <h1 style={{ textAlign: 'center' }}>Employee Tree</h1>
                    <h3>Test Case 1</h3>
                    <h4>Employee Tree</h4>
                    {employeeTree.map(manager => {
                        return (
                            <ul key={manager.id}>
                                <li style={{ fontWeight: 'bold' }}>
                                    <p>
                                        Employees of :
                                        {manager.empName.toLowerCase()}
                                    </p>
                                    <ul>
                                        {manager.children.map(employee => (
                                            <li type="square" key={employee.id}>
                                                {employee.empName.toLowerCase()}
                                                {employee.children.map(e => (
                                                    <div>
                                                        <li
                                                            key={e.id}
                                                            type="disc"
                                                            style={{
                                                                marginLeft:
                                                                    '120px',
                                                            }}>
                                                            {e.empName.toLowerCase()}
                                                        </li>
                                                    </div>
                                                ))}
                                            </li>
                                        ))}
                                    </ul>
                                </li>
                            </ul>
                        );
                    })}
                </div>
            </React.Fragment>
        </div>
    );
}

  // Convert flat array to tree, see https://stackoverflow.com/a/40732240/6695569
    const createEmployeeTree = data => {
        let hashTable = {};
        data.forEach(
            aData => (hashTable[aData.id] = { ...aData, children: [] })
        );
        let dataTree = [];
        data.forEach(aData => {
            if (aData.managerId) {
                if (!hashTable[aData.managerId]) return;
                hashTable[aData.managerId].children.push(hashTable[aData.id]);
            } else dataTree.push(hashTable[aData.id]);
        });
        return dataTree;
    };

  • Еще один совет, дон не используйте локальное состояние для производных значений, например, ваше show состояние было установлено в true, когда count было больше 0. Тогда вам нужно просто использовать вычисленное значение const show = count >0:
// instead of this

const [count, setCount] = useState(initialState);
const [show, setShow] = useState(false);
function(){
  setCount(0)
  setShow(false)
  ...
  if(count > 0) setShow(true)
  else setShow(false)
}

//do This

const [count, setCount] = useState(initialState);
const show = count > 0
  • Еще один совет, JSX очень легко разбить на компоненты, так что делайте это и не делайте очень длинные рендеры, которые могут быть очень трудными для чтения, вы можете разделить это так:
function Inhook(props) {
return (
<div>
  <Title />
  <Managers employeeTree={employeeTree} />
</div>
)
}

function Title(){
   return <h1 style={{ textAlign: 'center' }}>Employee Tree</h1>
}


function Managers({ employeeTree }) {
    return (
        <ul>
            {employeeTree.map(manager => (
                <li style={{ fontWeight: 'bold' }}>
                    <p>Employees of :{manager.empName.toLowerCase()}</p>

                    <Employees employees={manager.children} />
                </li>
            ))}
        </ul>
    );
}

function Employees({ employees }) {
    return (
        <ul>
            {employees.map(employee => (
                <li type="square" key={employee.id}>
                    {employee.empName.toLowerCase()}
                    {employee.children.map(e => (
                        <div>
                            <li
                                key={e.id}
                                type="disc"
                                style={{
                                    marginLeft: '120px',
                                }}>
                                {e.empName.toLowerCase()}
                            </li>
                        </div>
                    ))}
                </li>
            ))}
        </ul>
    );
}

0 голосов
/ 29 марта 2020

Вы изменяете состояние внутри рендера, вызывая val(s.id) в случае, если e.managerId === s.id истинно. Затем, когда они равны и , в то время как компонент пытается отобразить val(s.id) изменяет группу состояний в своем теле функции (val(e)), и компонент снова начинает отображаться до бесконечности.

Попробуйте и посмотрите, можете ли вы разделить проблемы в val(e), выдав несколько сеттеров, возможно, отдельную функцию для каждого. Кроме того, вычислите значение того, что вы хотите отобразить внутри «истинного» p-тега (вместо <p> {val(s.id)}</p>) вне рендера, а затем просто передайте его jsx!

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