Home > front end >  Why is my component rendering a count twice?
Why is my component rendering a count twice?

Time:10-02

my parent layout component:

function MainPage() {
    return(
        <div>
            <MLayout children={<MNavbar custOrFalse={false} />} />
        </div>
    );
}

export default MainPage;

my child navbar component:

 const Navbar = ({...props},{children}) => {

    const [grid, makeGrid] = useState(false); //whatever is inside the parenthesis is the starting value
    const [publish, makePublish] = useState(false);
    const [research, makeResearch] = useState(false);
    const [custOrFalse, makeCustToggle] = useState(props.custOrFalse);
    const [custCount,setCount] = useState(0);
   

    function CustToggle(){
      makeCustToggle(prevVal=>!prevVal); //useState is an async function, so need to use the previous value.
    }

    //can set this navbar to be cust based or not
    var custButton='cust page'
    if ( custOrFalse===true ) {
      custButton='cust login' 
    };
    var countFirst = (custCount == 0);
    console.log(countFirst)

    // useEffect(()=>{
    //   console.log(custCount);
    // },[custOrFalse]);
    console.log(custCount);

    return (
      <div>
          <nav className = {`${styles.page__menu} ${styles.page__custom_settings} ${styles.menu}`} >
            <ul className = {`${styles.menu__list} ${styles.r_list}`} >
                <CustomNavButtonLeft navbutton='the grid'         />
                <CustomNavButtonLeft navbutton='publish'          />
                <CustomNavButtonLeft navbutton='research'         />
                <CustomNavButtonRight navbutton={custButton} onClick={CustToggle,()=> setCount(custCount   1)}  />
            </ul>
          </nav>
          {custOrFalse&&<Registration/>}
          {countFirst&&!custOrFalse&&<DLogin/>}
      </div>
      );
  };


export default Navbar;

i'm trying to get the button on the navbar to toggle between texts as well as toggle between components it renders - BUT have the first rendering not show a component that i havent created yet, so in effect, show nothing.

when i run this code, the console log displays:

true
0
false

i was under the impression it would simply display true, but for some reason the count is made as soon as the component is rendered it seems?

from research what i understand, useEffect is an async function - but i'm not sure how that impacts the flow here

updated to show that once the counter is added, the toggle stops working

CodePudding user response:

if you're trying to call both the methods onClick you should do

onClick={()=>  { 
   CustToggle();
   setCount(custCount   1)
}}

``` instead of your current syntax

CodePudding user response:

Since you are using old value of custCount your state setter should accept a callback argument (state updates may be asynchronous in React).

()=> setCount(count=> count 1).

Also, you are initializing a state from props. This is an antipattern in React.

const [custOrFalse, makecustToggle] = useState(props.custOrFalse);

See this medium article:

Personally, I'd rewrite your Navbar component as follows, to use getDerivedStateFromProps :

class Navbar extends React.Component {

    constructor(props) {
        super(props);
        this.state = {grid:false, publish: false, research: false, custOrFalse: false, custCount: 0};
    }

    static getDerivedStateFromProps(props, state) {
        return {custOrFalse: props.custOrFalse};
    }


    custToggle = ()=>{
        this.setState(oldState=> {
            return {custToggle: !oldState.custToggle, custCount: oldState.custCount 1};
        });
    }
    

    render() {
        // .....
    }
}
    
  • Related