最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Update state based on key in React - Stack Overflow

programmeradmin3浏览0评论

I have state structure, something like this at the beginning:

messages:[
        {id: 1, name: 'name1'},
        {id: 2, name: 'name2'}, ...
    ]

What I want is to update one message based on its id key. I am getting from the server another object like this:

{id: 2, name: 'newName2'}

The state is an array: (2) [{…}, {…}]. I don't know which element with which index will be updated, I know only the id key inside the object.

How I can update object inside the state based on its key value ?

I have state structure, something like this at the beginning:

messages:[
        {id: 1, name: 'name1'},
        {id: 2, name: 'name2'}, ...
    ]

What I want is to update one message based on its id key. I am getting from the server another object like this:

{id: 2, name: 'newName2'}

The state is an array: (2) [{…}, {…}]. I don't know which element with which index will be updated, I know only the id key inside the object.

How I can update object inside the state based on its key value ?

Share Improve this question edited Apr 20, 2019 at 23:00 halfer 20.4k19 gold badges109 silver badges202 bronze badges asked Feb 15, 2019 at 15:51 gdfgdfggdfgdfg 3,5768 gold badges46 silver badges85 bronze badges 2
  • Maybe store them as key value pairs, or reduce your list to an object. messages.reduce ((m,o) => ({...m,[o.name]:o}),{})['name1']. You could also use messages.find(({name})=>name=='name1') – Moritz Roessler Commented Feb 15, 2019 at 15:57
  • Did any of the answers work for you? Consider accepting one of them if that's the case. – Tholle Commented Feb 15, 2019 at 22:13
Add a ment  | 

6 Answers 6

Reset to default 2

You can use findIndex to get the index of the object you want to update, and replace that with the new object in a new array and set that in your ponent state.

Example

class App extends React.Component {
  state = {
    messages: [{ id: 1, name: "name1" }, { id: 2, name: "name2" }]
  };

  updateMessage(newMessage) {
    this.setState(prevState => {
      const messages = [...prevState.messages];
      const index = messages.findIndex(m => m.id === newMessage.id);

      messages[index] = newMessage;

      return { messages };
    });
  }

  render() {
    return (
      <div>
        {this.state.messages.map(message => (
          <div key={message.id}>{message.name}</div>
        ))}
        <button onClick={() => this.updateMessage({ id: 2, name: "newName2" })}>
          Update message
        </button>
      </div>
    );
  }
}

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

<div id="root"></div>

You may be better of storing them as {key:'value'} pairs, if you need to look them up by a key.

You have a few options.

  • If your key is the id, and matches the index, you can access it directly.
  • Looping over your array
  • Use [].find
  • transform your list to an object and look it up.
  • use map
  • or findIndex
  • ..etc

let id = 1
let message = messages [id -1];
message.foo = 'bar';

let prop = 'name', key = 'name1'
for (const message of messages) if (message[prop] === key) message.foo = 'bar'

const byProp = (prop,key) => ({[prop]:k}) => k == key
const message = messages.find (byProp('name', 'name1'))

const byProp = (arr,prop) => arr.reduce ((obj, itm) => ({...obj, [itm[prop]]:itm}),{})
let message = byProp (messages, 'name')['name1']

This should work

 const newMsg = { id: 10, message: 'hi' }

 this.setState(({ messages } => {
    return {
       ...messages.filter(x => x.id !== newMsg.id),
       newMsg
    }
 };

Use Array.map to modify your array

const messages = [
    {id: 1, name: 'name1'},
    {id: 2, name: 'name2'},
]

const updateById = obj => {
  const { id } = obj;
  // here we check if new object has the same id as the old one
  // we replace old one with new
  return messages.map(message => message.id === id ? obj : message)
}

console.log(
  updateById({id: 1, name: 'newName'})
)

There are many ways to do this. One among them can be like below.

let x = [{id: 1, a: 1},{id: 2, b: 2}]

let newO = {id: 2, b: 3}

let y =[
    ...x.map(item => {
        if (item.id === newO.id) {
            return newO;
        } else return item
    })
]

console.log(y)

Here is a codesandbox that shows the code below in action.

Assuming you store your state like this:

    state = {
       messages: [
         { id: 1, name: 'name1' },
         { id: 2, name: 'name2' },
         { id: 3, name: 'name3' }
      ]
    }

Then, you can look for the message based on the id by using findIndex(), but you also want to make sure that you update your state immutably. So, you can do the following:

  changeMessage = (id, newName) => {

    // Search messages for a message with the given id, and return index
    // of the matching message in array, or -1 if not found.
    const arrayIndex = this.state.messages.findIndex((message) => (message.id === id))

    if (arrayIndex === -1) {
      console.log('No message found for id ' + id)
      return
    }

    // Copy over the messages from state to an array that
    // you can manipulate without affecting this.state.messages
    let updatedMessages = [...this.state.messages]

    // Update the message located by index
    updatedMessages[arrayIndex] = {
      id,
      name: newName
    }
    this.setState({
      messages: updatedMessages
    })
  }
}
发布评论

评论列表(0)

  1. 暂无评论