钩子和不变的状态

时间:2019-03-05 15:39:19

标签: reactjs react-hooks

如果在之前已经回答了这个问题,我会提前道歉(还有很长的帖子,但是我已经尽我所能了)。。但是,我找到的答案并不能完全让我满意。

我想在我的项目中使用新的惊人的React Hooks。到目前为止,我一直在做这件事。

现在我遇到了一个更复杂的示例,我不确定如何最好地解决这个问题。

比方说,我的状态中有更多的复杂对象(至少它不是平坦的)

{
    persons: [
        {
            id: 1,
            name: 'Joe Doe',
            age: 35,
            country: 'Spain',
            interests: [
                { id: 1, en: 'Football', es: 'Fútbol' },
                { id: 2, en: 'Travelling', es: 'Viajar' }
            ]
        },
        {
            id: 2,
            name: 'Foo Bar',
            age: 28,
            country: 'Spain',
            interests: [
                { id: 3, en: 'Computers', es: 'Computadoras' },
                { id: 4, en: 'Cooking', es: 'Cocinar' }
            ]
        }
    ],
    amount: 2,
    foo: 'bar'
}

什么是最好的方法?

  1. 将一个项目(对象)添加到我的同事数组中
  2. 将项目添加到特定的“兴趣”数组吗?
  3. 要操纵数组中对象的属性值吗?
  4. 要更改人员数组之外的值,例如foo

使用useState挂钩?

以下代码示例将尝试说明每个问题。他们未经测试...

让我们考虑一下我有一个以此开头的容器。 它还包括在其余文章中拆分的功能。

const [colleagues, setColleagues] = useState({});

// using the useEffect as "componentDidMount
useEffect(() => {

    // receiving data from ajax request
    // and set the state as the example object provided earlier
    setColleagues(response.data);
}, []);

1)因此,第一个问题。这有效吗? 还是我需要确保persons array中的每个对象都已解构?

const onAddNewColleague = () => {

    // new colleague, this data would be dynamic
    // but for the sake of this example I'll just hard code it
    const newColleague = {
        name: 'Foo Baz Bar',
        age: 30,
        country: 'Spain',
        interests: [
            { en: 'Cats', es: 'Gatos' }
        ]
    };

    // creates a copy of the state
    // targets the "persons" prop and adds a new array
    // where the new colleague is appended
    const newState = {
        ...colleagues,
        persons: colleagues.concat(newColleague)

    };

    // updates the state
    setColleagues(newState);
};

2),当我最终更新整个persons array而不是仅更新特定人的interest array时,这感觉不对。

const onAddNewInterest = (personId) => {
    // a new interest
    const newInterest = {
        en: 'Languages', es: 'Idiomas'
    };

    // find the person according to personId
    // and update the interests
    const updatedPersons = colleagues.persons.map(person => {
        if(person.id === personId) {
            return {
                ...person,
                interests: person.interests.concat(newInterest);
            };
        }

        return person;
    });

    // create a copy of the state
    const newState = {
        ...colleagues,
        persons: [...updatedPersons]
    };

    setColleagues(newState);
};

3)作为第二个示例,当我实际上只想更改其中一个的persons array时,我也更新了整个age具体的人

const onChangeValue = (personId, key, value) => {

    // find the person
    const updatedPersons = colleagues.persons.map(person => {

        if(person.id === personId) {
            // key, could be age?
            return {
                ...person,
                [key]: value
            };
        }

        return person;
    });

    // create a copy of the state
    const newState = {
        ...colleagues,
        persons: [...updatedPersons]
    };

    setColleagues(newState);
};

4),这是否有效,还是我需要分别销毁colleagues object的每个部分?

const onChangeOtherValue = (key, value) => {
    // for example changing the value foo

    const newState = {
        ...colleagues,
        [key]: value
    };

    setColleagues(newState);
};

我确实有一种感觉,只有第一个功能的概念有效,而其余的则无效。

这可以轻松完成吗,还是我应该只使用不可变的助手?

谢谢!

更新示例以获得正确的语法。谢谢Valerii。

要澄清 我真正想要的是处理此类用例的最佳实践。我想确保以最正确,最有效的方式更新我的状态。因此,请随意翻阅我的示例或撰写新示例-我全神贯注。不必简单地修改我的职位以适合该职位(除非他们实际上证明是好的)。

2 个答案:

答案 0 :(得分:0)

1)好

2)

    const updatedPersons = colleagues.persons.map(person => {
        if(person.id === personId) {
            return {
                ...person,
                interests: person.interests.concat({ en: 'Test', es: 'Test' })
            };
        }

        return person;
    });

    const newState = {
        ...colleagues,
        persons: updatedPersons
    };

3)

    const updatedPersons = colleagues.persons.map(person => {

        if(person.id === personId) {
            return {
                ...person,
                [key]: value
            };
        }

        return person;
    });

    // create a copy of the state
    const newState = {
        ...colleagues,
        persons: updatedPersons
    };

4)好

答案 1 :(得分:0)

对于第一个,我会这样做,

    const newState = {
          ...colleagues,
          persons: [...persons, newColleague]

    };