Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

replace object not trigger render #758

Closed
2 tasks
lake2 opened this issue Jul 12, 2023 · 3 comments
Closed
2 tasks

replace object not trigger render #758

lake2 opened this issue Jul 12, 2023 · 3 comments

Comments

@lake2
Copy link

lake2 commented Jul 12, 2023

Summary

const it = proxy({
    obj: { a: 1 },
});

setTimeout(() => {
    it.obj = { a: 2 };
}, 1000);

const A: React.FC = React.memo(function A(props) {
    const snap = useSnapshot(it.obj);
    console.log('===========update', snap); // only render once

    return (
        null
    );
});

Link to reproduction

Check List

Please do not ask questions in issues.

  • I've already opened a discussion before opening this issue, or already discussed in other media.

Please include a minimal reproduction.

@dai-shi
Copy link
Member

dai-shi commented Jul 12, 2023

const snap = useSnapshot(it.obj);
// that ☝️ means like this 👇 
const objThatNeverChanges = it.obj;
const snap = useSnapshot(objThatNeverChanges);

So, it's how JS works. The canonical fix is to subscribe to obj itself.

const { obj: snap } = useSnapshot(it);

@dai-shi dai-shi closed this as completed Jul 12, 2023
@lake2
Copy link
Author

lake2 commented Jul 13, 2023

const snap = useSnapshot(it.obj);
// that ☝️ means like this 👇 
const objThatNeverChanges = it.obj;
const snap = useSnapshot(objThatNeverChanges);

So, it's how JS works. The canonical fix is to subscribe to obj itself.

const { obj: snap } = useSnapshot(it);

Can I do something like replace the value to fix this?
Maybe I can make a PR to implement this replacement function and include it in valtio if this is reasonable;

const it = proxy({
    obj: { a: 1 },
});

// just a simple implementation, it may be not work in some situation
const replace = (it, key, value) => {
    Object.keys(value).forEach(item => {
        it[key][item] = value[item];
    });
};

setTimeout(() => {
    replace(it, 'obj', { a: 2 });
}, 1000);

const A: React.FC = React.memo(function A(props) {
    const snap = useSnapshot(it.obj);
    console.log('===========update', snap); // only render once

    return null;
});

@dai-shi
Copy link
Member

dai-shi commented Jul 13, 2023

It's a reasonable practice but you don't need to make a PR for that.
There are many other libraries that do similar things.
Feel free to submit a PR to improve docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants