Передача bool дочернему компоненту не работает правильно - PullRequest
0 голосов
/ 18 июня 2019

Я пытаюсь, чтобы у моего пользователя по желанию было текстовое поле, получить значение по умолчанию или нет.Заполните форму, чтобы записать, сколько товара доставлено.Может быть пустым или может автоматически рассчитывать, сколько товара должно прибыть на основе заказанного количества минус количество уже получено.Я могу сделать математику!

У меня есть логический набор с React Hooks, который переключается при нажатии на ссылку.Я надеялся, что это вызовет повторный рендеринг позиций с заполненным текстовым полем или без него, в зависимости от передачи «Автозаполнения» в коллекции реквизитов.Кажется достаточно простым.Работает как сон, если я жестко закодирую значение true или false в этом свойстве.Сбой полностью, если я вместо этого вставляю переменную.Я немного новичок в React, но я думал, что способен на это.Вероятно, пропущено что-то очевидное или неправильно понимается жизненный цикл и процесс рендеринга.

import React, { useState } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

function App() {

  const [af, setAf] = useState(false);

  const theList = [
    { Id: 1, Quantity: 7, Received: 4 },
    { Id: 2, Quantity: 4, Received: 0 }
  ];

  const setVal = (id, val) => {
    console.log(`Value for Id ${id} was set by child to ${val}`);
  };

  return (
    <div>
      <div onClick={() => setAf(!af)}>Toggle</div>
      {theList.map((itm, idx) => {
        return (
          <LineItem onChange={setVal} key={idx} AutoFill={af} Data={itm} />
        );
      })}
    </div>
  );
}

function LineItem(props) {
  const [val, setVal] = useState(
    props.AutoFill ? props.Data.Quantity - props.Data.Received : undefined
  );

  const setValue = newVal => {
    setVal(newVal);
    props.onChange(props.Data.Id, newVal);
  };

  return (
    <>
      <p>Value: {val}</p>
      <p>
        <input
          type="number"
          value={val}
          onChange={e => setValue(e.target.value)}
        />
      </p>
    </>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

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

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

1 Ответ

0 голосов
/ 18 июня 2019

Аргумент, переданный useState, используется только один раз, поэтому при изменении значения AutoFill prop состояние больше не оценивается. Для этого вам нужно использовать useEffect hook

const [val, setVal] = useState(
    props.AutoFill ? props.Data.Quantity - props.Data.Received : undefined
  );


  useEffect(() => {
     if(props.AutoFill) {
        setVal(props.Data.Quantity - props.Data.Received)
     }
  }, [props.AutoFill, props.Data.Quantity, props.Data.Received]);

Рабочая демоверсия

const { useState, useEffect } = React;
function App() {

  const [af, setAf] = useState(false);

  const theList = [
    { Id: 1, Quantity: 7, Received: 4 },
    { Id: 2, Quantity: 4, Received: 0 }
  ];

  const setVal = (id, val) => {
    console.log(`Value for Id ${id} was set by child to ${val}`);
  };


  return (
    <div>
      <div onClick={() => setAf(!af)}>Toggle</div>
      {theList.map((itm, idx) => {
        return (
          <LineItem onChange={setVal} key={idx} AutoFill={af} Data={itm} />
        );
      })}
    </div>
  );
}

function LineItem(props) {
  const [val, setVal] = useState(
    props.AutoFill ? props.Data.Quantity - props.Data.Received : undefined
  );

  const setValue = newVal => {
    setVal(newVal);
    props.onChange(props.Data.Id, newVal);
  };


  useEffect(() => {
     if(props.AutoFill) {
        setVal(props.Data.Quantity - props.Data.Received)
     }
  }, [props.AutoFill, props.Data.Quantity, props.Data.Received]);


  return (
    <React.Fragment>
      <p>Value: {val}</p>
      <p>
        <input
          type="number"
          value={val}
          onChange={e => setValue(e.target.value)}
        />
      </p>
    </React.Fragment>
  );
}

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