Попытка изменить данные из ответа React Promise изменяется глобально - PullRequest
0 голосов
/ 20 февраля 2020

Я создал коды и коробку с упрощенной версией моей проблемы

https://codesandbox.io/s/new-react-context-api-ei92k

Я что-то получаю из выборки (в данном случае от пользователя)

Затем я создаю локальную копию этого пользователя и вносю в нее некоторые изменения

Проблема: любые изменения обновляют мой первоначальный объект пользователя

Может кто-нибудь сказать мне, как это возможно? ? и как я могу избежать этого?

    import React, { useState, useEffect } from "react";
    import { AppSessionContext } from "./AppContext";
    import Header from "./Header";

    const user = {
      userName: "jsmith",
      firstName: "John",
      lastName: "Smith",
      isAdmin: true
    };
    const loadProfile = () => Promise.resolve(user);

    function createUserWithNewName(userToUpdate) {
      userToUpdate["userName"] = "Dummy";
      return userToUpdate;
    }

    const App = () => {
      const [user, setUser] = useState({});
      const [Loaded, setLoaded] = useState(false);

      var amendedUser = {};

      useEffect(() => {
        loadProfile()
          .then(user => {
            setUser(user);
            console.log(user);
          })
          .then(() => {
            amendedUser = createUserWithNewName(user);
            console.log(amendedUser);
            console.log(user);
          })
          .then(setLoaded(true));
      }, []);

      if (!Loaded) {
        return "Loading";
      }

      return (
        <AppSessionContext.Provider value={{ user }}>
          <div className="App">
            <Header />
          </div>
        </AppSessionContext.Provider>
      );
    };

    export default App;

фрагмент производственного кода

loadTableDefault() {

    fetch(defaultUrl(), {method: 'GET'})
    .then(res => res.json())
    .then(response => {
            this.setState({
                data: response,
            })
            return response
        }) 
    .then(response => {         
        this.setState({
            table_data: formatResponsePretty(response),
        })
    })
    .catch(error => console.error('Error:', error));
}

formatResponsePretty

export function formatResponsePretty(oldData) {

    const newData = {
        ...oldData,
    };
    // consider re-writting the flask response to this format
    const obj = { allocations: [] };
    var theRemovedElement = ''
    var ports = []

    ports = Object.values(newData['allocations']['columns']);
    ports.shift();

    var dataArray = ['allocations', 'conditions', 'liquidity', 'hedging']

    for (const index of dataArray) {
        for (const i of newData[index]['data']) {
            theRemovedElement = i.shift();
            if (index === 'allocations') {
                obj[index][theRemovedElement] = i
            }
            else {
                obj[theRemovedElement] = i;
            }
        }
    }

    const rows = []

    let index = 0;

    Object.keys(obj).forEach(element => {
        index = formatting.findIndex(x => x.name === element)
        if (formatting[index] && formatting[index]['type'] === 'number') {
            var new_obj = obj[element].map(function (el) {
                return Number(el * formatting[index]['multiplier']).toFixed(formatting[index]['decimal']) + formatting[index]['symbol']
            })
            rows.push(new_obj)
        }
        else if (formatting[index] && formatting[index]['type'] === 'string') {
            rows.push(obj[element])
        }
        else if (formatting[index] && formatting[index]['type'] === 'boolean') {
            // there should be logic here to display true or false instead of 1 and 0
            // this could be in the upload
            rows.push(obj[element])
        }
        else {
            rows.push(obj[element])
        }

    })

    const arrOfObj = createRecords(ports, rows)

    return {obj: obj, ports: ports, rows: rows, arrOfObj: arrOfObj}
}

1 Ответ

1 голос
/ 20 февраля 2020

В createUserWithNewName() вы обновляете исходный пользовательский объект и возвращаете его.

Вместо этого вы хотите создать новый объект со всеми старыми пользовательскими свойствами, но только с измененным именем пользователя. К счастью, деструктуризация объектов делает это очень просто:

function createUserWithNewName(oldUser) {
    const newUser = {
        ...oldUser,
        userName: 'Dummy',
    };

    return newUser;
}

Это скопирует все свойства oldUser в новый объект, а затем просто обновит userName!

Вы также Я хочу передать пользователя на эту секунду .then(), поскольку он там сейчас недоступен:

  .then(user => {
    setUser(user);
    console.log(user);
    return user;
  })
  .then(user => {
    amendedUser = createUserWithNewName(user);
    console.log(user, amendedUser);
  })

Обновить ссылку CodeSandbox: https://codesandbox.io/s/new-react-context-api-tgqi3

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...