【问题标题】:Change all values of nested state?更改嵌套状态的所有值?
【发布时间】:2019-09-15 12:06:05
【问题描述】:

我正在尝试创建一个组件,其中将通过几个父道具传递十几个嵌套值。

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

对于这个例子,我只会传递一些ChildProp,这里是一个例子prop:

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

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    缺少一些细节,但这大致就是您想要在两个单位之间转换的内容?

    几点说明:

    • 在这种情况下,button 可能是您想要的(而不是锚点:a
    • onClick回调需要传入一个函数() =&gt; 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>

    【讨论】:

    • 嗨,谢谢,我会试试这个。我还更新了一个代码框。
    • @kinx 根据您提供的内容用第二个示例更新了答案
    • 谢谢,你的例子让我有点困惑。虽然我提供了数据外观的示例,但它将通过 props 传递,例如 { someChildProp, someOtherChildProp }。这就是数据的来源。
    • 我假设,而不是示例字段属性,我会做 React.useState(someChildProp))?
    • 然后您可以在第一次使用React.useState(props. someChildProp) 渲染时“复制”它,或者您需要从允许更新该道具的父级传递一个道具,例如updateSomeChildProp,以便您的@987654331 @component 可以调用它。
    猜你喜欢
    • 2018-06-21
    • 2021-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多