Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
338 views
in Technique[技术] by (71.8m points)

reactjs - Why does React re-render differently whether the state is an object vs a string?

The below React example, userProfile state is an object:
1st render: state is {}
2nd render: state is res.data
-> infinite re-rendering

If userProfile is changed to a string e.g. useState('') with setUserProfile(res.data.bio)
1st render: state is ''
2nd render: state is res.data.bio
3rd render: state is res.data.bio
-> stops re-rendering after the 3rd

Two questions:

  • Why does React re-render differently depending on whether userProfile state is an object vs a string?
  • When userProfile is a string, why does React stop re-rendering after the 3rd render instead of after the 2nd one?

App.js

import UserProfile from './UserProfile';

const App = () => {
    const login = 'facebook';
    
    return (
        <Router>
            <Link to={`/user/${login}`}>Fetch Facebook bio from GitHub</Link>
            <Route path='/user/:login' component={UserProfile} />
        </Router>
    );
};

UserProfile.js

const UserProfile = ({ match }) => {
    const [userProfile, setUserProfile] = useState({});

    const getUser = async username => {
        const url = `https://api.github.com/users/${username}`;
        const res = await axios.get(url);
        setUserProfile(res.data);
    };

    getUser(match.params.login);
// intentionally not using useEffect(() => { getUser(match.params.login); }, []);

    return (<p>{userProfile.bio}</p>);
};
question from:https://stackoverflow.com/questions/66057904/why-does-react-re-render-differently-whether-the-state-is-an-object-vs-a-string

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

React checks if a state variable has changed, and if so, it rerenders. Since no matter how many times you compare two objects (even if they look identical), they will always be different, React will keep rerendering.

A string, on the other hand, is a primitive type and thus compares differently. Try this:

console.log({d: 3} === {d: 3})
console.log("sss" === "sss")

And it will give you an idea as to why this happens.

So even though you keep setting the state var to the same object, it's not really the same. But a string IS the same so it stops rerendering.

Check out this article on Object equality in JS: http://adripofjavascript.com/blog/drips/object-equality-in-javascript.html

Now let me address your second question:

When userProfile is a string, why does React stop re-rendering after the 3rd render instead of after the 2nd one?

If you look at the React Docs, you will run into these 2 paragraphs, which, I believe answer your question:

If you update a State Hook to the same value as the current state, React will bail out without rendering the children or firing effects. (React uses the Object.is comparison algorithm.)

Note that React may still need to render that specific component again before bailing out. That shouldn’t be a concern because React won’t unnecessarily go “deeper” into the tree. If you’re doing expensive calculations while rendering, you can optimize them with useMemo

Note the second paragraph.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...