【问题标题】:handle multiple checkboxes and complex data structure (reactjs)处理多个复选框和复杂的数据结构(reactjs)
【发布时间】:2019-04-14 00:39:57
【问题描述】:

由于我对 React 还很陌生,也不是 JS 尤其是 ES6 方面的专家,我想知道如何使我的代码(有效)更漂亮并重构它。

我想在一个表单中处理多个复选框并将当前值存储在状态对象中。由于复选框是分组的,我想要一个像这样被回答的任务的结构:

{  
   "isLoaded":true,
   "answeredTasks":{  
      "1":[  
         "green",
         "blue",
         "red"
      ],
      "5":[  
         "car",
         "cat",
         "house"
      ]
   }
}

这是我在复选框上的 onChange 方法:

  checkBoxOnChange = e => {
    let currentAnswers = this.state.answeredTasks;

    let element = e.currentTarget;

    // if it is the first answer checked
    if (currentAnswers[element.name] === undefined) {
      currentAnswers[element.name] = [];
    }

    // if uncheck
    if (!element.checked) {
      const index = currentAnswers[element.name].indexOf(element.value);
      currentAnswers[element.name].splice(index, 1);
    } else {
      currentAnswers[element.name].push(element.value);
    }

    this.setState({ answeredTasks: currentAnswers });
  };

你能告诉我如何改进我的方法,尤其是使用 ES6 吗? 我大部分时间都在努力创建数据结构。

谢谢。

【问题讨论】:

  • 您能否将代码提供给您的整个组件代码?此外,作为建议,请避免在代码中使用“let”,而应使用“const”来避免改变数据。尝试学习函数式编程范式,这是最佳行业实践。

标签: javascript arrays reactjs object ecmascript-6


【解决方案1】:

我不是第一个,但这是我的测试版本

static changeAnswers = ({target: {name, value, checked}}) => 
  checked
    ? { ...answeredTasks, ...{ [name]: [...(answeredTasks[name] || []), value] } }
    : {
        ...answeredTasks,
        ...{ [name]: (answeredTasks[name] || []).filter(e => e !== value) }
      }

checkBoxOnChange = e => {
  const {answeredTasks} = this.state
  this.setState({answeredTasks: myComponent.changeAnswers(e)})
}

const answeredTasks = { "1": ["green", "blue", "red"] }

const elements = [
  { name: "1", value: "green", checked: false },
  { name: "1", value: "black", checked: true },
  { name: "2", value: "lol", checked: true },
  { name: "2", value: "lol", checked: false }
]

const click = ({ name, value, checked }) =>
  checked
    ? { ...answeredTasks, ...{ [name]: [...(answeredTasks[name] || []), value] } }
    : {
        ...answeredTasks,
        ...{ [name]: (answeredTasks[name] || []).filter(e => e !== value) }
      }

elements.map(element => console.log(click(element)))

【讨论】:

    【解决方案2】:

    我希望我能看到你的整个代码。 但是,如果我想建议您进行任何更改:

    1. 一般来说,避免在代码中使用“let”,而应使用“const”。这样,您可以避免更改数据,这是行业最佳实践,React 文档强烈建议这样做。

    2. 避免使用改变数据的 splice/push/pop 方法,而是使用数组函数,例如 filter/map/some/every 等...我提到的方法不会改变数据,而是返回一个不同的引用对象。

    这是你应该做的改变:

    checkBoxOnChange = e => {
        const currentAnswers = this.state.answeredTasks;
        const element = e.target;
    
        const newAnswers = !element.checked ?
            (currentAnswers[element.name] || []).filter(val => val !== element.value) :
            (currentAnswers[element.name] || []).concat(element.value);  
    
        this.setState({ answeredTasks: {...currentAnswers, newAnswers} });
     };
    

    请注意,setState() 函数中的 {...currentAnswers, newAnswers} 将 currentAnswers 与 newAnswers 中的新更改合并。即 newAnswers 将覆盖外部数组中的特定对象。 这是函数式的做事方式。

    【讨论】:

    • "let" 而是使用 "const" - 在对象的情况下并不重要。当你“改变”一个数组或对象时,你没有重新分配或重新声明常量,它已经被声明和分配,你只是添加到常量指向的“列表”中。
    • 维克多,你有点糊涂了。突变不是重新声明一个新对象,这正是它不好的原因! ...函数式编程不喜欢副作用,也不喜欢对引用相同的对象进行更改。不变性意味着您应该在每次新更改时引用创建一个新对象,这是行业最佳实践,ReactJs 强烈推荐它。
    • 使用 splice/pop/push 等方法修改对象/数组正在改变对象(更改同一个对象),而使用 map/filter/some/every 则不是。它们将引用地返回一个新的对象/数组,这是“纯粹”的做事方式,因此被 ReactJs 推荐。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-31
    • 2020-07-18
    • 1970-01-01
    • 2017-07-02
    • 1970-01-01
    • 2019-02-13
    相关资源
    最近更新 更多