更改嵌套状态的所有值?

时间:2019-09-15 03:46:50

标签: javascript reactjs

我正在尝试创建一个组件,在该组件中将传递十二个嵌套值以及一些父项。

在此组件中,我有两个按钮,每个按钮都有一个onClick事件,当我按下该按钮时,我试图将其嵌套,以便将嵌套prop的值传递给函数并进行更改,并在视图中进行更新。

在此示例中,我仅传递someChildProp,这是一个示例道具:

List.defaultProps = {
  someChildProp: {
    field1: 1.4,
    field2: 1.2,
    field3: 1.6,
    field4: 1.1
  }
};

当您按下任一按钮时:

<a className="unit-selected" onClick={handleUnitClick('unit1')}>
  Unit 1
</a>
<span>/</span>
<a onClick={handleUnitClick('unit2')}>
  Unit 2
</a>

这将运行handleUnitClick,它将检查传递的值,然后在我设置所有道具的位置运行该函数。

  const handeUnitClick = (type) => {
    if (type === 'unit1') {
      convertProps();
    }
  }
  const convertProps = () => {
    Object.keys(someChildProp).map((item, index) => {
      // set new value with convertUnit(number)
      // concat to new object?
      // set state again?
    })
  }
  const convertUnit = (number) => {
    return number + 5;
  }

因此,设置新状态在.map中看起来像这样。

  someChildProp: {
    key[index]: convertUnit(value)
  }

我不确定该怎么做,如何映射每个对象,更改值,设置整个ChildProp的状态?

所以我被困在这一点上:

  const convertProps = () => {
    Object.keys(someChildProp).map((item, index) => {
      // set new value with convertUnit(number)
      // concat to new object?
      // set state again?
    })
  }

我该怎么做?

以下是全部代码:https://codesandbox.io/embed/competent-firefly-soyv4

1 个答案:

答案 0 :(得分:1)

缺少一些细节,但这大概就是您想要的能够在两个单位之间转换的东西吗?

一些注意事项:

  • 在这种情况下,您可能想要一个button(而不是锚点:a
  • 对于onClick回调,您需要传递函数() => this. handleUnitClick('unit1')

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      someChildProp: {
        field1: 1.4,
        field2: 1.2,
        field3: 1.6,
        field4: 1.1
      }
    };
  }

  handleUnitClick = type => {
    if (type === "unit1") {
      this.convertProps(this.convertUnitOne);
    } else if (type === "unit2") {
      this.convertProps(this.convertUnitTwo);
    }
  };

  convertProps = convertFn => {
    const someChildProp = {};

    Object.keys(this.state.someChildProp).forEach(item => {
      someChildProp[item] = convertFn(this.state.someChildProp[item]);
    });

    this.setState({ someChildProp });
  };

  convertUnitOne = number => {
    return number + 5;
  };

  convertUnitTwo = number => {
    return number / 5;
  };

  render() {
    return (
      <React.Fragment>
        <button onClick={() => this.handleUnitClick("unit1")}>Unit 1</button>
        <button onClick={() => this.handleUnitClick("unit2")}>Unit 2</button>
        <ul>
          <li>{this.state.someChildProp.field1}</li>
          <li>{this.state.someChildProp.field2}</li>
          <li>{this.state.someChildProp.field3}</li>
          <li>{this.state.someChildProp.field4}</li>
        </ul>
      </React.Fragment>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<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="root"></div>

或者,使用挂钩代替您的Codesandbox。

最大的问题是您正在使用无法更改的默认道具(使用当前设置)。似乎更合适的方法是状态,或使用带有对象默认值(而不是默认道具)的钩子useState

const List = ({ someChildProp }) => {
  const [values, setValues] = React.useState({
    field1: 1.4,
    field2: 1.2,
    field3: 1.6,
    field4: 1.1
  })

  const handleUnitClick = type => {
    if (type === "unit1") {
      convertProps();
    }
  };

  const convertProps = () => {
    const newValues = {};

    Object.keys(values).forEach((key) => {
      newValues[key] = convertUnit(values[key])
    });

    setValues(newValues)
  };

  const convertUnit = number => {
    return number + 5;
  };

  return (
    <div className="modal-items">
      <header className="modal">
        <h3>List</h3>
      </header>
      <div className="unit-options">
        <a className="unit-selected" onClick={() => handleUnitClick("unit1")}>
          Unit 1
        </a>
        <span>/</span>
        <a onClick={() => handleUnitClick("unit2")}>Unit 2</a>
      </div>
      <div className="items-table-container">
        <div className="items-table items-performance">
          <h4 className="items-title">Performance</h4>
          <ul className="items">
            <li className="items-spec">
              <div className="items-spec-label">Field 1</div>
              <div className="items-spec-value">{values.field1}</div>
            </li>
            <li className="items-spec">
              <div className="items-spec-label">Field 2</div>
              <div className="items-spec-value">{values.field2}</div>
            </li>
            <li className="items-spec">
              <div className="items-spec-label">Field 3</div>
              <div className="items-spec-value">{values.field3}</div>
            </li>
            <li className="items-spec">
              <div className="items-spec-label">Field 4</div>
              <div className="items-spec-value">{values.field4}</div>
            </li>
          </ul>
        </div>
      </div>
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<List />, rootElement);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>