useReducer init as props

Why is there an error here:

Objects are not valid as a React child (found: object with keys
{count}). If you meant to render a collection of children, use an
array instead.

If you do not use prop init there is no error

import { useReducer } from "react";

function init(initialCount) {
    return { count: initialCount };

function reducer(state, action) {
    switch (action.type) {
        case "increment":
            return { count: +state.count + 1 };
        case "decrement":
            return { count: +state.count - 1 };
        case "reset":
            return init(action.payload);
            throw new Error();

function Counter({reducer, initialCount, init}) {
    const [state, dispatch] = useReducer(reducer, initialCount, init);
    return (
            Count: {state.count}
                onClick={() =>
                    dispatch({ type: "reset", payload: initialCount })
                {" "}
            <button onClick={() => dispatch({ type: "decrement" })}>-</button>
            <button onClick={() => dispatch({ type: "increment" })}>+</button>

export default function App() {
    return (
        <div className="App">
            {/* <Counter reducer={reducer} initialCount={{count: 0}} /> */}
            <Counter reducer={reducer} initialCount={{count: 0}} init={init} />          

>Solution :

In such situation:

  const [state, dispatch] = useReducer(reducer, initialArg, init);

The docs say:

You can also create the initial state lazily. To do this, you can pass
an init function as the third argument. The initial state will be set
to init(initialArg).

in your case initialArg is same as initialCount which is an object, hence it will call below function with object as argument:

function init(initialCount) {
    return { count: initialCount };

and it will return object, where count refers to an object too. And then you are trying to render an object, and react complains.

Leave a Reply