why onClick isn't working on my react project - javascript

onclick isn't working on my react component, here is my code:
const listItems = xox.map((nums) =>
<Square key={nums.index} cont={nums.content} onclick={function (){
alert();
}}/>
);
also i tried this but alert working on the when render the page:
<Square key={nums.index} cont={nums.content} onclick={alert()}/>
my app function:
function App() {
return (
<div className="App">
<header>
<img src={logo} alt="React logo"/>
<h1>XOX</h1>
</header>
<div className="playground">
{listItems}
</div>
</div>
);
}
Square.js
import React from "react";
export class Square extends React.Component {
render() {
return (
<div className="square" onClick={this.props.onclick}>
{this.props.cont}
</div>
)
}
}

You need to make sure your Square component accepts and then uses an onclick prop. For example, something like:
const Square = ({ cont, onclick }) => (
<div onClick={onclick}>{cont}</div>
);
Otherwise the prop will be ignored, since it's not used inside the component.
also i tried this but alert working on the when render the page:
Yes, you need to pass a function as a prop, not invoke the function then pass the result as a prop. This:
return <Square key={nums.index} cont={nums.content} onclick={alert()}/>
is equivalent to doing
const result = alert();
return <Square key={nums.index} cont={nums.content} onclick={result}/>;
So you instead need
onclick={() => alert()}
(or with the function keyword as you're already doing, though it's less terse)
If possible, I'd also suggest using the standard capitalization for React click handlers, which is onClick, not onclick - there's less chance of confusing people that way.

try using arrow functions:
<Square key={nums.index} cont={nums.content} onClick={() => alert('hello world')}/>

Related

why does my prop cease to exist after initially existing when I pass it through to a functional component?

This is the function where I am passing the onClick prop (setShowModal is setState() from the useState hook):
<MyFunctionalComponent
onClick={() => setShowModal(true)}
...other props here
/>
This is the functional component that receives the prop:
export const MyFunctionalComponent = ({ onClick }) => {
return (
<section>
...other code here
{onClick && (<Button>{ctaText}</Button>)}
</section>
);
};
But the Button component never appears, because the prop onClick is undefined. When I console.log the prop inside the functional component, it initially prints the function in the console, but then prints two more times as undefined. Could someone explain why that would be? I got it to work by spreading ...props instead. But the console.log remains the same? I don't understand why. This is my first question on Stack Overflow, so feel free to give me feedback on how to ask better questions :)
The reason why you are receiving an 'undefined' response is because as #Zrogua mentioned, onClick is an event listener function rather than a persistent value (like state you define).
import React from "react";
const YourButton = ({ onClick }) => {
console.log(onClick);
return <section>{onClick && <button>here</button>}</section>;
};
const ParentDiv = () => {
return (
<div>
<h1>Button Props</h1>
<h2>Start editing to see some magic happen!</h2>
<YourButton onClick={() => console.log("CLICK")} />
</div>
);
};
export default ParentDiv;
Result of console.log():
function onClick() // index.js:27:25
The reason why this is because props are read-only. From the React Docs:
Whether you declare a component as a function or a class, it must never modify its own props ... Such functions are called “pure” because they do not attempt to change their inputs, and always return the same result for the same inputs.
Therefore your button will only show if the onClick function is defined. For example, if you did not give onClick a function or value, the button will not appear:
import React, { useState } from "react";
const YourButton = ({ onClick }) => {
console.log(onClick);
return (
<section>
{onClick && <button>This button is shown if a button is defined.</button>}
</section>
);
};
const ParentDiv = () => {
return (
<div>
<h1>Button Props</h1>
<YourButton onClick={() => console.log("CLICK")} />
<YourButton /> {/* You won't see this button because the function is not defined. */}
</div>
);
};
export default ParentDiv;
The button appears because the prop has a value that is not undefined (your onClick function), and because it is read-only, you cannot access that function in your child component.
Instead, (1) define the modal state in the parent component and (2) pass the state through props to the button like so:
import React, { useState } from "react";
const YourButton = ({ onClick }) => {
console.log(onClick);
return (
<section>
{onClick && <button>This button is shown if a button is defined.</button>}
</section>
);
};
const AltButton = ({ modal }) => {
return (
<section>
{modal && (
<button>This button is shown the modal state is passed.</button>
)}
</section>
);
};
const ParentDiv = () => {
const [modal, setModal] = useState(false);
return (
<div>
<h1>Button Props</h1>
<YourButton onClick={() => console.log("CLICK")} />
<YourButton />{" "}
{/* You won't see this button because the function is not defined. */}
<section>
<button onClick={() => setModal(!modal)}>OPEN MODAL</button>
</section>
{modal && <p>this is dependent on state</p>}
<AltButton modal={modal} />
</div>
);
};
export default ParentDiv;
Working CodeSandbox: https://codesandbox.io/s/stack-66715327-passingfunctions-92pzr
Finally, if I am reading between the lines and understanding correctly that you are looking to hide a button when a modal is open, here is a little modal wrapper trick I use for buttons that open modals: https://codesandbox.io/s/stack-66715327-modalwrapper-wvl54
You can't pass onClick, onClick is just an event listener. You should pass the state
<MyFunctionalComponent onClick={() => setShowModal(!showModal)}
showModal={showModal}
...other props here />
/>
export const MyFunctionalComponent = ({ showModal }) => {
return (
<section>
...other code here
{showModal && (<Button>{ctaText}</Button>)}
</section>
);
};
I believe this should work. Let me know if this is what you were looking for.
I think that rather then passing callback you should pass variable which decide if component should show or not. Check this example.
export const MyFunctionalComponent = ({ isShow, onClick }) => {
return (
<section>
...other code here
{isShow && <div>something</div>}
</section>
);
};
export default function App() {
const [showModal, setShowModal] = useState(false);
return (
<MyFunctionalComponent
isShow={showModal}
onClick={() => setShowModal(true)}
/>
);
}
I also suppose that you can make mistake and have something other on mind .. like this:
<section>
...other code here
<button onClick={ onClick }>something</button>}
</section>

Can't pass useState() 'set' function to grand child

I'm having issues trying to get my useState variable to work. I create the state in my grandparent then pass it into my parent. Here's a simplified version of my code:
export function Grandparent(){
return(
<div>
const [selectedID, setSelectedID] = useState("0")
<Parent setSelectedID2={setSelectedID} .../> //(elipses just mean that I'm passing other params too)
<div />
)}
Parent:
const Parent = ({setSelectedID2 ...}) => {
return(
<div>
{setSelectedID2("5")} //works
<Child setSelectedID3={setSelectedID2} />
</div>
)
}
From the parent I can use 'setSelectedID2' like a function and can change the state. However, when I try to use it in the child component below I get an error stating 'setSelectedID3' is not a function. I'm pretty new to react so I'm not sure if I'm completely missing something. Why can I use the 'set' function in parent but not child when they're getting passed the same way?
Child:
const Child = ({setSelectedID3 ...}) => {
return(
<div >
{setSelectedID3("10")} //results in error
</div>
);
};
In React you make your calculations within the components/functions (it's the js part) and then what you return from them is JSX (it's the html part).
export function Grandparent(){
const [selectedID, setSelectedID] = useState("0");
return(
<div>
<Parent setSelectedID2={setSelectedID} .../> //(elipses just mean that I'm passing other params too)
<div />
)}
You can also use (but not define!) some js variables in JSX, as long as they are "renderable" by JSX (they are not Objects - look for React console warnings).
That's your React.101 :)
Here's a working example with everything you have listed here. Props are passed and the function is called in each.
You don't need to name your props 1,2,3.., they are scoped to the function so it's fine if they are the same.
I moved useState and function calls above the return statement, because that's where that logic should go in a component. The jsx is only used for logic dealing with your display/output.
https://codesandbox.io/s/stupefied-tree-uiqw5?file=/src/App.js
Also, I created a working example with a onClick since that's what you will be doing.
https://codesandbox.io/s/compassionate-violet-dt897?file=/src/App.js
import React, { useState } from "react";
export default function App() {
return <Grandparent />;
}
const Grandparent = () => {
const [selectedID, setSelectedID] = useState("0");
return (
<div>
{selectedID}
<Parent setSelectedID={setSelectedID} selectedID={selectedID} />
</div>
);
};
const Parent = ({ selectedID, setSelectedID }) => {
setSelectedID("5");
return (
<div>
{selectedID}
<Child setSelectedID={setSelectedID} selectedID={selectedID} />
</div>
);
};
const Child = ({ selectedID, setSelectedID }) => {
setSelectedID("10");
return <div>{selectedID}</div>;
};
output
10
10
10
const [selectedID, setSelectedID] = useState("0")
should be outside return

Pass arguments to function in React (API)

Today I started learning React, and I want to fetch movies from the TMDb API. I have this code:
getMovies() {
const APIKey = "MYAPI";
fetch(`https://api.themoviedb.org/3/search/company?api_key=${APIKey}&query=${argument}&page=1`)
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(myJson);
});
}
And in my render() I have this:
return (
<Fragment>
<div className="Main">
<button onClick={this.getMovies.bind('spider-man')}>Get</button>
</div>
</Fragment>
)
I want to pass 'spider-man' as an argument to do the search in the TMDb API. Hope you can help me!
This is how you can pass the parameter to the class component function, using {() => {...}} or other option could be this.getMovies.bind(this, 'spider-man')
getMovies(movie) { // your code here}
Option 1:
return (
<Fragment>
<div className="Main">
<button onClick={() => this.getMovies('spider-man')}>Get</button>
</div>
</Fragment>
)
Option 2:
return (
<Fragment>
<div className="Main">
<button onClick={() => this.getMovies.bind(this,'spider-man')}>Get</button>
</div>
</Fragment>
)
This is mainly divided into two categories
Class components
Functional Components
Class components
Consider you have your code as follow:
getMovies(movieName){...}
render(){
<button onClick={/*Attach event here*/}>Get</button>
}
There can be 4 ways
Using binding in the constructor, This is a recommended way of binding a method.
class Movie{
constructor(props){
super(props);
this.getMovies = this.getMovies.bind(this);
}
getMovies(movieName){ //your code }
render(){
<button onClick={this.getMovies('some_movie_name')}>Get</button>
}
}
Using binding in the render method itself. In terms of performance, it's the same as the previous one. The first one is a little cleaner for me.
class Movie{
getMovies(movieName){ //your code }
render(){
<button onClick={this.getMovies.bind('some_movie_name')}>Get</button>
}
}
Using arrow function syntax in render().
class Movie{
getMovies(movieName){ //your code }
render(){
<button onClick={()=>this.getMovies('some_movie_name')}>Get</button>
}
}
Using the arrow function in classes. This will have an impact on overall performance. You can read more about this here.
class Movie{
getMovies = (movieName) => { //your code }
render(){
<button onClick={this.getMovies('some_movie_name')}>Get</button>
}
}
Function components
Consider you have your code as follow:
function getMovies(movieName){ //your code }
return(){
<button onClick={/*Attach event here*/}>Get</button>
}
There aren't many variations for the function component. Using either an arrow or regular function expression to define a function.
function Movie(){
function getMovies(movieName){...} //or const getMovies = (movieName) => {...}
return(
<button onClick={()=>getMovies('some_movie_name')}>Get</button>
{/*
if not arguments
<button onClick={getMovies}>Get</button>
*/}
)
}

return component with hook in react?

I have 2 components. I want to keep component A clean, hence I don't wish to use useState in it, I wish to use useState in component B, but since the component B isn't a hook (because it return the jsx as well), how can I call stateHandler in component A?
const ComponentA = () => {
return (
<div>
<ComponentB />
<button onClick={()=>{
//what to do here to control the state of component B?
}}>show component B</button>
</div>
)
}
const ComponentB = () => {
//I don't want to move this setShowBlock to index.js for clean code purpose
const [showBlock, setShowBlock] = useState(false)
return (
<div>
{showBlock && <div>component B</div>}
</div>
)
}
https://stackblitz.com/edit/react-ggtt87?file=index.js
you can use context as central store,
in the context you create the useState hook with showBlock and setShowBlock and then you can change it from component A
const ComponentA = () => {
const {setShowBlock} = useContext(MyContext)
return (
<div>
<ComponentB />
<button onClick={()=>{
here call setShowBlock and change it
}}>show component B</button>
</div>
)
}

ReactJS remove dynamic element

i want to remove dynamic element in my program, but i think, i have problem with 'this'.When i click in 'X', nothing happens, console doesn't show any error. Maybe someone more experienced will help me.
('items' is array in state)
Main file:
removeItemCity(i){
let arr = this.state.items;
arr.splice(i, 1);
this.setState({items:arr})
}
renderItems(item,i){
return(<Tiles key = {'key_' + i} index = {i} delete = {() =>
{this.removeItemCity}}/>);
}
render() {
return(
<div className = "BodyAppContainer">
<div className = "grid" id="items">
{this.state.items.map(this.renderItems) }
</div>
</div>
);
}
And my component "Tiles"
import React from 'react';
class Tiles extends React.Component {
constructor(props) {
super(props);
}
remove(){
this.props.delete(this.props.index);
}
render() {
return (
<div className = "col-4_sm-6_xs-12 item">
<h2>City : {this.props.index}</h2>
<button className="removeButton" onClick={() => this.remove} >X</button>
</div>
);
}
}
export default Tiles;
Your onClick prop for the X button is not doing anything:
onClick={() => this.remove}
When you click, it calls that arrow function. But that arrow function only has this.remove, which is the definition to a method. The first step in helping you out is you should call that method using parentheses:
onClick={() => this.remove()}
The same thing applies to your renderItems(), where you are also missing parentheses to enact a function call in the delete prop passed to Tiles:
delete={() => {this.removeItemCity}}
Try this:
<button className="removeButton" onClick={this.remove} >X</button>

Categories