猿问

React - 如何循环和更新对象模型中的值?

我有一个对象模型模式如下


   this.state = {

        data: {

            audi: {

                 engine: '2.5',

                 gearbox: 'auto',

                 fuel: 'petrol'

             },

             bmw: {

                 engine: '3.0',

                 gearbox: 'auto',

                 fuel: 'petrol'

             },

             merc: {

                 engine: '6.3',

                 gearbox: 'manual',

                 fuel: 'petrol'

             }

         }

    }

我的目标是:

  1. 循环数据并渲染

  2. 将 HTML 中的值更改映射到 this.state.data 对象中的相应键

我没有使用数组,因为在发布它时它必须看起来像上面的对象模式。

目前我正在尝试这样做:

//To render

Object.entries(this.state.data).map((x,index) =>

    <p>x.key</p> //Trying to reach 'audi' with x.key


    // Render each KPV in object

    {x.key}: <input key={index} onChange={this.handleChange} value={x.value}/>

)

然后更新同一状态模型中的相应值:


// To update the state model with changed values

setData = (key, val) => {

    this.setState(state => ({

        data: {

            ...state.data,

            obj: { [key]: val },

            //Don't know how to map to state properly!

        }

    }));

};


// Handle input change

handleChange = key => e => {

    this.setData(key, e.target.value);

};

请任何人就这种方法向我提出建议,非常感谢:)


波斯汪
浏览 163回答 3
3回答

哆啦的时光机

首先,您需要正确渲染,这意味着循环所有键(汽车制造商),然后循环所有属性/值对。您可以使用解构数组来简化此操作Object.entries(someObject).map( ([key,value]) => .... )继承人渲染:render() {&nbsp; &nbsp; return Object.entries(this.state.data).map(([maker, props]) => {&nbsp; &nbsp; &nbsp; return (&nbsp; &nbsp; &nbsp; &nbsp; <div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <h2>{maker}</h2>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {Object.entries(props).map(([key, value], index) => {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return (&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {key}:{" "}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <input&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; key={index}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onChange={this.handleChange(maker, key)}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; defaultValue={value}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; );&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; })}&nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; );&nbsp; &nbsp; });&nbsp; }您会注意到我更改了您的handleChange方法来传递汽车制造商和正在编辑的属性 - 这可以传递到setData:// To update the state model with changed values&nbsp; setData = (maker, key, val) => {&nbsp; &nbsp; this.setState((state) => ({&nbsp; &nbsp; &nbsp; data: {&nbsp; &nbsp; &nbsp; &nbsp; ...state.data,&nbsp; &nbsp; &nbsp; &nbsp; [maker]: {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...state.data[maker],&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [key]: val&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; //Don't know how to map to state properly! Now you do!&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }));&nbsp; };&nbsp; // Handle input change&nbsp; handleChange = (maker, key) => (e) => {&nbsp; &nbsp; this.setData(maker, key, e.target.value);&nbsp; };实时工作示例:https ://codesandbox.io/s/react-playground-forked-dw9sg

繁星coding

您首先没有从输入回调传递键和事件对象,您的代码应该是这样的,显示逻辑在我看来是错误的,Object.entries(this.state.data).map((x, index) =>&nbsp; &nbsp; /*&nbsp;&nbsp; &nbsp; &nbsp;here x is an array and it looks like&nbsp;&nbsp; &nbsp; &nbsp;["audi", {engine: '2.5', gearbox: 'auto', fuel: 'petrol}&nbsp; &nbsp; */&nbsp; &nbsp; &nbsp;// You need to access the data in the second index&nbsp; &nbsp; &nbsp;// if you want to print each value of the object&nbsp; &nbsp; <p>x[1].engine</p>&nbsp; &nbsp; <p>x[1].gearbox</p>&nbsp; &nbsp; <p>x[1].fuel</p>&nbsp;&nbsp; &nbsp; // Render each KPV in object&nbsp; &nbsp; {x[0]}: <input key={index} onChange={(e) => this.handleChange(x[0], e)} value={x[1].engine}/>)回调handleChange应该看起来像,不要柯里化它们。handleChange = (key, e) => {&nbsp; &nbsp; this.setData(key, e.target.value);};我建议使用 lodash 的castArray之类的实用程序,https://lodash.com/docs/4.17.15#castArray将对象转换为数组,以便您可以轻松使用它。

杨__羊羊

class App extends React.Component {&nbsp; constructor(props) {&nbsp; &nbsp; super(props)&nbsp; &nbsp; this.state = {&nbsp;&nbsp; &nbsp; &nbsp; data: {&nbsp; &nbsp; &nbsp; &nbsp; audi: { model: "A7", transmission: "AT" },&nbsp; &nbsp; &nbsp; &nbsp; merc: { model: "GLA", transmission: "MT" },&nbsp; &nbsp; &nbsp; &nbsp; bmw: { model: "M3", transmission: "AT" },&nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; }&nbsp; }&nbsp; update(make, detail, value) {&nbsp; &nbsp; let data = this.state.data&nbsp; &nbsp; data[make][detail] = value&nbsp; &nbsp; console.log(`Updating ${make} ${detail} with ${value}`)&nbsp; &nbsp; this.setState({ data: data })&nbsp; }&nbsp; handleChange(make, detail) {&nbsp; &nbsp; return e => { this.update(make, detail, e.target.value) }&nbsp; }&nbsp; renderDetails(details) {&nbsp; &nbsp; return details.map(d => (<div><span>{d.key}:</span> <input value={d.model} onChange={this.handleChange(d.key, "model")} /> <input value={d.transmission} onChange={this.handleChange(d.key, "transmission")} /></div>))&nbsp; }&nbsp; render() {&nbsp; &nbsp; const details = Object.entries(this.state.data).map(d => ({ key: d[0], ...d[1] }))&nbsp; &nbsp; return <div>{this.renderDetails(details)}</div>&nbsp; }}ReactDOM.render((<App />), document.getElementById("app"))body { font-family: monospace; }span { display: block; font-weight: bold; }input { width: 50px; }<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="app"></div>
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答