Age Verification Popup Show Only Once BY Account instead of by Cookie Memory

Greeting,
I am doing an age verification popup targeted only to the landing page of login.

The show-only-once function was set but only for cookie memory of the browser. That is- if I login to the same account in other device or incognito/ inPrivate, it will show up anyway, and vise versa.

Here are the script code for the age verification. Not sure if there is options for account-based show-only-once.


jQuery(document).ready(function($){
 
if (sessionStorage.getItem('advertOnce') !== 'true') {
//sessionStorage.setItem('advertOnce','true');
 $('.box').show();
}else{
 $('.box').hide();
}
 
$('#refresh-page').on('click',function(){
$('.box').hide();
sessionStorage.setItem('advertOnce','true');
});
 
$('#reset-session').on('click',function(){
$('.box').show();
sessionStorage.setItem('advertOnce','');
});
 
if (sessionStorage.getItem('advertOnce') !== 'true') {
//sessionStorage.setItem('advertOnce','true');
 $('.overlay-verify ').show();
}else{
 $('.overlay-verify ').hide();
}
 
$('#refresh-page').on('click',function(){
$('.overlay-verify ').hide();
sessionStorage.setItem('advertOnce','true');
});
 
$('#reset-session').on('click',function(){
$('.overlay-verify ').show();
sessionStorage.setItem('advertOnce','');
});
 
 
});

Many thanks

how can i get connection from edge of circle insted of center of circle in d3.js force layout

here im added the link  from  circle center to circle center but i want to connect from circle edge to edge

Here im added the link from circle center to circle center but i want to connect from circle edge to edge

I want to connect the links from node edge to edge but im getting node center to center
is i did mistake in my code please help me out if any one know answer for this problem

here is my full working code

const VocabularyGraphh = () => {
  const svgRef = useRef(null);
  React.useEffect(() => {
    const svg = d3.select(svgRef.current),
      diameter = +svg.attr("width"),
      g = svg.append("g").attr("transform", "translate(2,2)"),
      format = d3.format(",d");

    const links = [
      { source: "animate1", target: "animate4" },
      { source: "animate6", target: "animate9" },
      //   { source: "animate9", target: "animate6" },
      { source: "animate3", target: "animate2" },
      { source: "animate1", target: "animate8" },
      { source: "animate3", target: "animate5" },
      //   { source: "analytics1", target: "analytics2" },
    ];

    let root = {
      children: [
        {
          name: "analytics1",
          children: [
            {
              name: "animate1",
              size: 1500,
            },
            {
              name: "animate2",
              size: 1500,
            },
            {
              name: "animate3",
              size: 1500,
            },
            {
              name: "animate33",
              size: 1500,
            },
            {
              name: "animate23",
              size: 1500,
            },
            {
              name: "animate32",
              size: 1500,
            },
            {
              name: "animate11",
              size: 1500,
            },
            {
              name: "animate22",
              size: 1500,
            },
            {
              name: "animate34",
              size: 1500,
            },
            {
              name: "animate16",
              size: 1500,
            },
            {
              name: "animate20",
              size: 1500,
            },
            {
              name: "animate3",
              size: 1500,
            },
          ],
        },
        {
          name: "analytics2",
          children: [
            {
              name: "animate4",
              size: 1500,
            },
            {
              name: "animate5",
              size: 1500,
            },
            {
              name: "animate6",
              size: 1500,
            },
          ],
        },
        {
          name: "analytics3",
          children: [
            {
              name: "animate7",
              size: 1500,
            },
            {
              name: "animate8",
              size: 1500,
            },
            {
              name: "animate9",
              size: 1500,
            },
          ],
        },
      ],
    };

    // svg
    //   .append("svg:defs")
    //   .append("svg:marker")
    //   .attr("id", "arrow")
    //   .attr("viewBox", "0 0 10 10")
    //   .attr("refX", 10)
    //   .attr("refY", 5)
    //   .attr("markerUnits", "strokeWidth")
    //   .attr("markerWidth", 6)
    //   .attr("markerHeight", 3)
    //   .attr("orient", "auto")
    //   .append("svg:path")
    //   .style("stroke", "none")
    //   .attr("d", "M 0 0 L 10 5 L 0 10 z");

    const pack = d3
      .pack()
      .size([diameter / 2, diameter / 2])
      .padding(100);

    root = d3
      .hierarchy(root)
      .sum(function (d) {
        return d.size;
      })
      .sort(function (a, b) {
        return b.value - a.value;
      });

    const node = g
      .selectAll(".node")
      .data(pack(root).descendants())
      .enter()
      .filter(function (d) {
        return !!d.data.name;
      })
      .append("g")
      .attr("id", function (d) {
        return d.data.name;
      })
      .attr("class", function (d) {
        return d.children ? "node" : "leaf node";
      })
      .attr("transform", function (d) {
        return "translate(" + d.x + "," + d.y + ")";
      });

    node.append("title").text(function (d) {
      return d.data.name + "n" + format(d.value);
    });

    const arrow = svg.selectAll("path.arrow").data(links, JSON.stringify);
    arrow
      .enter()
      .append("path")
      .attr("class", "arrow")
      .attr("x1", function (d) {
        console.log(d);
        let translate = getTranslate(d.source);
        console.log(translate);
        return translate[0];
      })
      .attr("x2", function (d) {
        let translate = getTranslate(d.target);
        return translate[0];
      })
      .attr("y1", function (d) {
        let translate = getTranslate(d.source);
        return translate[1];
      })
      .attr("y2", function (d) {
        let translate = getTranslate(d.target);
        return translate[1];
      })
      .attr("d", function (d) {
        // console.log(d);
        let source = getTranslate(d.source),
          target = getTranslate(d.target),
          x1 = source[0],
          x2 = target[0],
          y1 = source[1],
          y2 = target[1];
        console.log(source);
        console.log(target);
        // let dx = x1 - x2,
        //   dy = y1 - y2,
        //   dr = Math.sqrt(dx * dx + dy * dy);

        return (
          "M" + x1 + "," + y1 + "A" + 0 + "," + 0 + " 0 0,1 " + x2 + "," + y2
        );
      })
      .style("stroke", "black")
      .style("fill", "none")
      .style("stroke-width", 1)
      .attr("marker-end", "url(#arrow)")
      .attr("class", "hidden-arrow ");
    //   .attr("stroke-width", 1);

    node
      .append("circle")
      .attr("r", function (d) {
        console.log(d);
        return d.r;
      })
      .attr("class", "pink");

    node.filter(function (d) {
      return !d.children;
    });
    //   .append("text")
    //   .attr("dy", "0.3em")
    //   .text(function (d) {
    //     return d.data.name.substring(0, d.r / 3);
    //   });

    function getTranslate(datum) {
      const circle = d3.select("#" + datum);
      const string = circle.attr("transform");
      const translate = string
        .substring(string.indexOf("(") + 1, string.indexOf(")"))
        .split(",");
      return translate;
    }
  }, []);
  return (
    <div>
      <svg ref={svgRef} width="960" height="960"></svg>
    </div>
  );
};

export default VocabularyGraphh;

if anyone give this solution thats so appreciatable

Google map api. search nearby not getting respond back seem link axios getting skip

Hello guys I am working on google map api to search all the gym near by me using Vue Js and laravel. The problem is I am not getting an error back and also not getting an respond back here is my code.

 <template>
  <div class="container mb-5">
    <div class="row justify-content-center">
      <div class="col-md-12 text-center">
        <h1 class="">Find</h1>
      </div>
      <div class="row mt-5">
        <form>
          <div class="form-group">
            <label>Email address</label>
            <input
              type="text"
              class="form-control"
              placeholder="Address"
              v-model="coordinates"
            />
            <a @click="locatorButtonPressed"> get location</a>
          </div>
          <select class="form-control" v-model="type">
            <option value="gym">gym</option>
          </select>
          <select
            class="form-control"
            v-model="radius"
            aria-placeholder="Distance"
          >
            <option value="10">10 KM</option>
            <option value="50">50 KM</option>
            <option value="100">100 KM</option>
            <option value="200">200 KM</option>
          </select>
          <button class="ui button" @click="findCloseBuyButtonPressed()">
            Find Gym
          </button>
        </form>
      </div>
    </div>
  </div>
</template>

<script>
import axios from "axios";

export default {
  name: "App",
  data() {
    return {
      lat: 0,
      lng: 0,
      type: "",
      radius: "",
      places: [],
    };
  },
  computed: {
    coordinates() {
      return `${this.lat}, ${this.lng}`;
    },
  },
  methods: {
    locatorButtonPressed() {
      navigator.geolocation.getCurrentPosition(
        (position) => {
          this.lat = position.coords.latitude;
          this.lng = position.coords.longitude;
        },
        (error) => {
          console.log("Error getting location");
        }
      );
    },
    findCloseBuyButtonPressed() {
 

      var axios = require('axios');

      var config = {
        method: 'get',
        url:  `https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${
                this.lat
              },${this.lng}&type=${this.type}&radius=${
                this.radius * 1000
              }&key={my-api-key}`,
        headers: { }
      };
      alert(config.url)
      axios(config)
      .then(function (response) {
        console.log(JSON.stringify(response.data ));
      })
      .catch(function (error) {
        console.log(error);
      });
      alert("hello")
    },
  }
};
</script>

<style>
</style>

I have try to debug this code by putting alert() it pop us both but it seems that it skipped this part because there is not respond or error in console

 axios(config)
  .then(function (response) {
    console.log(JSON.stringify(response.data ));
  })
  .catch(function (error) {
    console.log(error);
  });

So I try changed alert to console.log() this time it just refresh a page and return noting in a console.

I have try my google map api key with example from document on website it still work fine.

How do I let the browser allow me to use imports? (TypeScript)

Context

I have these two TypeScript files:

// something.ts

let x = 3;

export default x;
// index.ts

import x from "./something";

console.log(x);

under these tsconfig.json settings:

{
  ...
    "target": "es2016",
  ...
    // "module": "commonjs" /* <- commented out */
}

when I compile this into JavaScript, I get these two files (which is what I expect):

// something.js

let x = 3;
export default x;
// index.js

import x from "./something";
console.log(x);

Now, I’ve linked the index.js file from my HTML file like so:

<script src="./dist/index.js"></script>

Problem

When I try opening this up using Live Server, I get this error in the console:

Uncaught SyntaxError: Cannot use import statement outside a module

So, how do I fix this?

What I’ve tried

  1. Adding back the "module": "commonjs" line in my tsconfig.json file

This results in a different error message appearing in the console:

Uncaught ReferenceError: exports is not defined

As per this SO post, a suggested solution is to comment out the "module": "commonjs" line, which essentially throws my situation into an infinite loop…

  1. Adding "type": "module" to the <script> tag and package.json

From this SO post, a suggested solution is to add "type": "module" to the <script> tag:

<script type="module" src="./dist/index.js"></script>

but now I get this error message:

GET http://127.0.0.1:5501/dist/something net::ERR_ABORTED 404 (Not Found).

In the same post, another suggestion was to add “type”: “module” to the package.json file:

{
  "type": "module",
  "dependencies": {
    "typescript": "^4.6.2"
  }
}

and from what I’ve observed, this doesn’t really do anything.

Key value in javascript

This is the continuation of this question which is here How to group by dynamic key value of an object of arrays(Month and year) Here i am getting output as expected but i want a small change on the output. The out put which is producing right now is as follows.
enter image description here

But the result which i am expecting is goes like this.

enter image description here
Code which i am using is like this.

           //Stack to retrive result
              let filteredStack:any =[];
            //Sorting based on the sorted key
              sortedKeys.forEach(k => {
                filteredStack.push(k,result[k]);
              });

How can i do this?

This “undefined” error has been driving me crazy! Can you find the error? [duplicate]

The code below references a td object with id “00”. I’m simply trying to get the the background color (which is currently expected to be “white”). I’ve declared the background in CSS as “white”. I can’t figure out how the statement below would result in an error. Can you?

console.log(document.getElementById("00").style.backgroundColor);

Length issue with Javascript carry-forward choices from multiple questions using Qualtrics?

I am using a matrix drag and drop on Qualtrics to ask respondents to sort 46 statements into the categories: agree less, neutral, and agree more (QID1).

QID1

In QID6 I ask them to sort the statements carried forward from the category agree less into -5 to 0.

QID6

Then in QID7 I ask them to sort the statements carried forward from the category agree more into 0 to 5.

QID7

In QID4 I show them how they sorted the statements (from -5 to 5) from QID6 and QID7. However, I wanted to combine how they sorted the responses in QID1, QID6, and QID7 specifically for the neutral and 0 responses. However, I have been unsuccessful at getting all the statements to carry forward. If only one statement was put into each of the categories of neutral (in QID1), category 0 in QID6, and category 0 in QID7 then those three statements appear in QID4.(QID1selection, QID6selection, QID7selection, result)

However, if more than one statement is placed into any of those categories (neutral in QID1 or 0 in QID6 and 7), then none of them appear in QID4. This does not seem to be an issue for the statements selected in the other categories (-5,-4,-3,-2,-1,1,2,3,4,5). Is this an issue with length or is concat the incorrect function to use? I am not familiar with javascript at all, so I am having a hard time figuring out what is the issue.

Below is the Javascript function I am using (based on this discussion post: https://community.qualtrics.com/XMcommunity/discussion/14728/carry-forward-response-into-drag-drop-box)

    Qualtrics.SurveyEngine.addOnReady(function () {
    let ques = this;
    //let a1 = "${q://QID1/ChoiceGroup/SelectedChoicesForAnswer/1}";
    let a2 = "${q://QID1/ChoiceGroup/SelectedChoicesForAnswer/2}"; //this is neutral
    //let a3 = "${q://QID1/ChoiceGroup/SelectedChoicesForAnswer/3}";
    let b1 = "${q://QID6/ChoiceGroup/SelectedChoicesForAnswer/1}";
    let b2 = "${q://QID6/ChoiceGroup/SelectedChoicesForAnswer/2}";
    let b3 = "${q://QID6/ChoiceGroup/SelectedChoicesForAnswer/3}";
    let b4 = "${q://QID6/ChoiceGroup/SelectedChoicesForAnswer/4}";
    let b5 = "${q://QID6/ChoiceGroup/SelectedChoicesForAnswer/5}";
    let b6 = "${q://QID6/ChoiceGroup/SelectedChoicesForAnswer/6}"; //this is 0
    let c1 = "${q://QID7/ChoiceGroup/SelectedChoicesForAnswer/1}"; //this is 0
    let c2 = "${q://QID7/ChoiceGroup/SelectedChoicesForAnswer/2}";
    let c3 = "${q://QID7/ChoiceGroup/SelectedChoicesForAnswer/3}";
    let c4 = "${q://QID7/ChoiceGroup/SelectedChoicesForAnswer/4}";
    let c5 = "${q://QID7/ChoiceGroup/SelectedChoicesForAnswer/5}";
    let c6 = "${q://QID7/ChoiceGroup/SelectedChoicesForAnswer/6}";
    
    let d1 = a2.concat(b6,c1); //this should combine all the statements selected for QID1 (ans2), QID6 (ans6), and QID7 (ans1)
    
    let choice_text = ques.getChoiceContainer().innerText.split(/n/gm);
    let all_choices = ques.getChoices();
    let all_answers = ques.getAnswers();
    
    for (let i = 0; i < choice_text.length; i++) {
        let set_choice= -1
        switch (true) {
            case b1.includes(choice_text[i]):
                set_choice = all_answers[0];
                break;
            case b2.includes(choice_text[i]):
                set_choice = all_answers[1];
                break;
            case b3.includes(choice_text[i]):
                set_choice = all_answers[2];
                break;
             case b4.includes(choice_text[i]):
                set_choice = all_answers[3];
                break;
             case b5.includes(choice_text[i]):
                set_choice = all_answers[4];
                break;
            case d1.includes(choice_text[i]): //this should show all the statements selected for QID1 (ans2), QID6 (ans6), and QID7 (ans1)
                set_choice = all_answers[5];
                break;  
            case c2.includes(choice_text[i]):
                set_choice = all_answers[6];
                break;
            case c3.includes(choice_text[i]):
                set_choice = all_answers[7];
                break;
             case c4.includes(choice_text[i]):
                set_choice = all_answers[8];
                break;
             case c5.includes(choice_text[i]):
                set_choice = all_answers[9];
                break;
            case c6.includes(choice_text[i]):
                set_choice = all_answers[10];
                break;
        }
        ques.setChoiceValue(all_choices[i], set_choice, true);
    }
});

I would appreciate it if anyone can point me to the right direction or to any helpful resources.

Automatic scroll to the current song in the playlist

I have a div with vertical scrollbar. It contains a list of 20 songs, with variable length titles. At any given moment, the div can display only 7 songs.

I am able to highlight the song being played in the div, however, it remains hidden under the div, as moving to the next song refreshes the page and the div scroll to the top.

Q. How do I scroll the div such that the current song (and preferably prev and next) always remain in the view?

Any points are greatly appreciated!

JS using dot, string notation to map nested and assign errors

Ok, this is an odd one that I just can’t seem to get right.

I have a large, complex object to send to a backend. After various attempts, I tried using Joi to validate the schema, and I like it, but passing the errors back to the inputs is a nightmare

The body is subdivided into 5 sections, with each subsection containing between 10-30 fields, some of which are string[], interface[], number[], or general nested interfaces.

I tried writing my own custom validation and the complexity grew outta control.

(I know some of you are thinking “your schema is too complex” and you’re right, but its not something I can change right now. Clients blah blah.)

The problem: Joi.validate(myBody) gives me a bunch of errors in the following format:

[ // <- error.details
  {
    context: {},
    message: "X is not allowed to be empty",
    path:["path","to","property"], // <- this is the key
    type: ""
  }
]

How can I map error.details to create a new validation object that I can then use for the form items themselves.

For example:

path = ["path","to","property"] // -> map over to create

let newObj = {
  path:{
    to: {
       property: ""
    }
}
}

I hope this make sense.

I want to take an array of vallidation errors, and turn them into a validation object that matches the initial object

Yarn local node modules checksum verification

I came across the following statement:

“Yarn uses checksums to verify the integrity of every installed package before its code is executed.”

I am not able to find details however on how this actually works.

As a test, I have modified the integrity fields in yarn.lock to random values and yarn seems not to be performing any checks on them.

Does that mean that it’s pulling those values from the npm repository every time automatically?

Google analytics data in react application

I,m working on an admin dashboard of a react web application and I want to use google analytics to track my web app data. I know how to do it in google analytics but actually, I want to get the data from google analytics to my website admin dashboard.

I’ve been looking for that in a lot of resources but I couldn’t find a good information resource. Here I want to track the data using google analytics ad display it inside my website admin dashboard.

Uncaught TypeError: signinUsingGoogle is not a function

I’m trying to add firebase authentication to my website. but having an error. I’m trying to solve this last three days. below I’m shared my code and error. i use react router dom, firebase authentication system with react js. when I click sign in with google button, it show hello in console, that’s right. but after it, I’m facing this error.

the error is,
error screenshot

in useFirebase.js file, I write below code,

import React, { useEffect, useState } from 'react';
import { getAuth, GoogleAuthProvider, onAuthStateChanged, signInWithPopup } from "firebase/auth";
import initializeConfig from '../Firebase/Firebase.init';

initializeConfig();

const useFirebase = () => {
    const auth = getAuth();
    const provider = new GoogleAuthProvider();
    const [user, setUser] = useState({});

    

    const signinUsingGoogle = () => {
        return signInWithPopup(auth, provider)
    }



    useEffect(() => {
        const unsubscribed = onAuthStateChanged(auth, user => {
            if (user) {
                setUser(user)
            }
            else {
                setUser({})
            }
        });
        return () => unsubscribed;
    }, [])



    const signOut = () => {
        signOut(auth)
            .then(() => {
            
        })
    }
    return (
        user,
        signinUsingGoogle,
        signOut

    );
};

export default useFirebase;

and in signin.js file, I write the below code,

import React from "react";
import { Button } from "react-bootstrap";
import { useLocation, useNavigate } from "react-router-dom";
import useAuth from "../../Hooks/useAuth";
import "./Signin.css";

const Signin = () => {
    const { signinUsingGoogle } = useAuth();
    const navigate = useNavigate();
    const location = useLocation();
    const navigateUrl = location?.state?.from || "/home";
    const GoogleSignin = () => {
        console.log("hello");
        signinUsingGoogle()
            .then((result) => {
                navigate(navigateUrl);
            })
            .finally(() => {});
    };

    return (
        <div className="signin d-flex justify-content-center align-items-center mx-auto">
            <div className="signin-card p-3 m-3">
                <img
                    src="https://c.tenor.com/9Xf0d7BGQ5oAAAAC/computer-log-in.gif"
                    alt="img not found"
                    width="360px"
                />
                <div className="d-grid gap-2 mt-3 text-center">
                    <Button variant="primary" size="lg" onClick={GoogleSignin}>
                        <h5>
                            <i className="fab fa-google-plus"></i> Google
                        </h5>
                    </Button>
                    <Button variant="secondary" size="lg" className="github">
                        <h5>
                            <i className="fab fa-github"></i> Github
                        </h5>
                    </Button>
                    <Button variant="secondary" size="lg" className="facebook">
                        <h5>
                            <i className="fa-brands fa-facebook"></i> Facebook
                        </h5>
                    </Button>
                </div>
            </div>
        </div>
    );
};

export default Signin;

I’m confused with declaring a let variable , closure, functions and lexical environment in JS [duplicate]

My prof provided me with the following code:

function makeCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

let counter = makeCounter();

alert( counter() ); // 0
alert( counter() ); // 1
alert( counter() ); // 2

I know that counter() is being called. But I don’t see any function named as counter. Could someone shred some lights?

Display checkmark svg on top of theme on click of particular theme

I want to display themes ( can be image or div ) and when user selects particular theme checkmark-inside-circle svg in overlay should be displayed on top but transparent so that theme below should be visible (dummy example). Considering theme as mat-radio-button , below is code

HTML

<div class="text-container" name="themeList">
   <mat-radio-group formControlName="theme" aria-label="Select a theme" class="theme-radio-group">
       <mat-radio-button
         *ngFor="let op of themeId; let i = index"
          name="themeList"
          class="theme-radio"
          [value]="i"
          (click)="selectThemeOnClick(i)">

          <div *ngIf="i == 0; else elseBlock">Theme {{i + 1}} (Default) </div>

          <ng-template #elseBlock>Theme {{i + 1}}</ng-template>
          <div #radio [attr.id]=i class="theme-radio-div themeDiv"></div>

        </mat-radio-button>
    </mat-radio-group>
</div>

In above code getting data from array and adding theme name ( default for 1st ) and adding themeDiv with it’s ID.
Tried to display checkmark for 1st theme but was not able to do that ( [checked]=”i === 0″ inside mat-radio-button , didn’t worked )

CSS

:host ::ng-deep .mat-radio-container {
  display: none;
}

.theme-container {
  .text-container {
    .theme-radio-group {
      display: grid;
      grid-gap: 20px;
      grid-template-columns: repeat(3, 226px);
      align-content: space-around;
      justify-content: space-between;

  .themeDiv {
    content: url('example.jpg');
    width: 226px;
    height: 142px;
  }

  .theme-radio-check-mark {
    width:24px;
    height: 24px;
    content: url('check-mark-in-circle.svg');
    opacity: 0.5;
    position:relative;
    left:100px;
    top:60px;
  }
}
 }
}

Hiding radio buttons just showing themeDiv for selection, using grid as div has to be of fixed size ( want to use flexbox , but space-between property creates problem in last row ). Checkmark has to be in middle of div. opacity also didn’t worked .

TS

public selectThemeOnClick(value) {
    this.themeValueId = value;
    const themeRadioDivArray = Array.from(document.querySelectorAll(".theme-radio-div"));
    if (themeRadioDivArray) {
      themeRadioDivArray
      .filter(element => element.classList.contains("theme-radio-check-mark"))
      .forEach((element) => {
          element.classList.remove("theme-radio-check-mark");
      });
    }
    const themeRadioDiv = document.getElementById(this.themeValueId);
    if (themeRadioDiv) {
      themeRadioDiv.classList.add("theme-radio-check-mark");
    }
  }

If clicked on theme, removing class from all other elements and adding class to that clicked theme.

I could only think of replacing div with svg content using css.

Struggling to do following :

  1. Checkmark should be displayed for default theme (considering 1st one for now)
  2. Display checkmark on overlay for selected theme
  3. Use flexbox

Trying to make a tic-tac-toe app, why doesn’t my component work as expected?

quick question on reactjs. So I’m new to react and I’m trying to make a tic-tac-toe application.

Currently, this is what I have:
App.js:

import logo from './logo.svg';
import './App.css';
import { Row } from './components/Row';
import {Board} from './components/Board'

function App() {
  // App renders Row
  return (
    <div>
      <Board />
    </div>
    
  );
}

export default App;

Board.js

import React from "react";
import { ReactDOM } from "react";
import { Row } from "./Row";

export function Board() {
    return (
        <div className="Board">
            <Row />
            <Row />
            <Row />
        </div>
    )
}

Row.js

import React from 'react';
import ReactDOM from 'react-dom';
import { Square } from './Square';

export function Row() {

    return(
        <div className='Row'>
            <Square />
            <Square />
            <Square />
        </div>
    )
}

Square.js

import React, {useState} from 'react';
import ReactDOM from 'react-dom';

export function Square(props){
    // Square is rendered by App
    const [currLetter, changeLetter] = useState(" ");

    function toggleLetter(str) {
        if(str === " ") {return "X";}
        else if(str === "X") {return "O";}
        else if(str === "O") {return "X";}
    }

    return(
        <div >
            <button onClick={() => changeLetter(toggleLetter)} className='Square'> {currLetter} </button>
        
        </div>
               
    );
}

and it works well, but I’m wondering why it doesn’t work when I write Square.js like this:

export function Square(props){
    // Square is rendered by App
    const [currLetter, changeLetter] = useState("X");

    function toggleLetter(str) {
        if(str === "X") {changeLetter("O");}
        else if(str === "O") {changeLetter("X");}
    }

    return(
        <div >
            <button onClick={toggleLetter} className='Square'> {currLetter} </button>
        
        </div>
               
    );
}

why can’t onClick just take in toggleLetter as is? it’s a function right?

second question
this is what my css looks like:

.Board {
  display: flex;
  flex-direction: column;
  justify-content: space-between;

  
  /* width: 55%;
  height: 55%; */
  margin-top: 18%;
}


.Row {
  text-align: center;
  /* position: absolute; */
  /* left: 35%;
  right: 50%;
  top: 25%;
  
  width: 25%;
  height: 25%; */

  display: flex;
  flex-direction: row;
  justify-content: center;

  
}
.Square {
  /* position: absolute; */
  
  width: 70px;
  height: 70px;
  border-color: #99ccff;
  text-align: center;
  font-size: xx-large;
  font-family: 'Courier New', Courier, monospace;
}
/* .Row {

} */

.App-logo {
  height: 40vmin;
  pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
  .App-logo {
    animation: App-logo-spin infinite 20s linear;
  }
}

.App-header {
  background-color: #282c34;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin);
  color: white;
}

.App-link {
  color: #61dafb;
}

@keyframes App-logo-spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

body {
  min-height: 100%;
  margin: 0;
  padding: 0;
  background-color: #ffcccc;
}
html {
  height: 100%;
}

What I wanted to do was make sure the board is centred in body, and therefore centred on the page. As it is, it is centred on the page but then the body is moved down. When I inspect the page, the top edge of the body is moved down to the same level of the top edge of board, as opposed to the body being where it was by default and the board being in its centre. How do I fix this?

what it looks like:

how-it’s-going