disable another button on react js - javascript

I have a React project which has three buttons in it. When I click a button, For example I click the second button, it will log "this is from button two ". followed by a random number with time interval 500ms. My aim is when I click a button, another buttons will be disabled, how to do this? Thanks in advance.
This is my App.js
import './App.css';
import { Button1 } from './Button1.React';
import { Button2 } from './Button2.React';
import { Button3 } from './Button3.React';
function App() {
return (
<div className="App">
<Button1>log one</Button1>
<Button2>log two</Button2>
<Button3>log three</Button3>
</div>
);
}
export default App;
this is my Button1.React.jsx
import React from "react";
export const Button1 = ({
children,
type,
doStuff1 = ()=> {
console.log("this is button one ", Math.random().toFixed(1));
setTimeout(doStuff1, 500);
},
})=>{
return (
<button onClick={doStuff1} type={type}>
{children}
</button>
)
};
this is my Button2.React.jsx
import React from "react";
export const Button2 = ({
children,
type,
doStuff2 = ()=> {
console.log("this is button two ", Math.random().toFixed(1));
setTimeout(doStuff2, 500);
}
})=>{
return (
<button onClick={doStuff2}type={type}>
{children}
</button>
)
};
this is my Button3.React.jsx
import React, { Children } from "react";
export const Button3 = ({
children,
type,
doStuff3 = ()=> {
console.log("this is button three ", Math.random().toFixed(1));
setTimeout(doStuff3, 500);
}
})=>{
return (
<button onClick={doStuff3}type={type}>
{children}
</button>
)
};
and here's the screenshot from the rendered page
i've been told to do this is using useState that returns a boolean condition to disable/enable click, but i don't know how to do this.

function App() {
const [bool1, setBool1] = useState(false);
const [bool2, setBool2] = useState(false);
const onClickBtn1 = () => {
// your other codes when btn 1 is clicked
// ------
setBool2(true); //disable button 2
}
const onClickBtn2 = () => {
// your codes when btn 2 is clicked
// ------
setBool1(true); //disable button 1
}
return (
<div className="App">
<button onClick={onClickBtn1} disabled={bool1}>Button 1</button>
<button onClick={onClickBtn2} disabled={bool2}>Button 2</button>
</div>
);
}
Basically, you use disabled in the button element, the value of the disabled should be in the state so the app will re-render if its value changes. Finally, change the value of the state on the button's onClick handler. You need to learn to use React Hooks for this since you said you don't know useState.

Is this what you try to do
import React, { useState } from "react";
const Button = ({ children, type, disabled, doStuff }) => {
return (
<button onClick={doStuff} type={type} disabled={disabled}>
{children}
</button>
);
};
export default function Name() {
const [activeButton, setActiveButton] = useState();
const disableOtherButtons = (currentButton) => {
if (activeButton === currentButton) {
setActiveButton()
} else {
setActiveButton(currentButton)
}
}
const doStuff1 = () => {
console.log("this is button one ", Math.random().toFixed(1));
disableOtherButtons('button1');
};
const doStuff2 = () => {
console.log("this is button one ", Math.random().toFixed(1));
disableOtherButtons("button2");
};
const doStuff3 = () => {
console.log("this is button one ", Math.random().toFixed(1));
disableOtherButtons("button3");
};
return (
<div>
<Button
doStuff={doStuff1}
disabled={activeButton && activeButton !== "button1"}
>
Button1
</Button>
<Button
doStuff={doStuff2}
disabled={activeButton && activeButton !== "button2"}
>
Button2
</Button>
<Button
doStuff={doStuff3}
disabled={activeButton && activeButton !== "button3"}
>
Button2
</Button>
</div>
);
}

You can pass reference useState to buttons
import { useRef } from 'react';
import './App.css';
import { Button1 } from './Button1.React';
import { Button2 } from './Button2.React';
import { Button3 } from './Button3.React';
function App() {
const [ btn1, setBtn1 ] = useState(false) // by default disabled will be set to false
const [ btn2, setBtn3 ] = useState(false)
const [ btn3, setBtn3 ] = useState(false)
const actions = [ setBtn1, setBtn2, setBtn3 ]
return (
<div className="App">
<Button1 actions={actions} disabled={btn1}>log one</Button1>
<Button2 actions={actions} disabled={btn2}>log two</Button2>
<Button3 actions={actions} disabled={btn3}>log three</Button3>
</div>
);
}
export default App;
and for buttons you need to accept those parameters and work with them
import React from "react";
export const Button1 = (props) => {
const { children, type, actions, disabled } = props
const doStuff = () => {
actions[0](false); // this will set Button1 to disabled
console.log("this is button three ", Math.random().toFixed(1));
setTimeout(doStuff3, 500);
}
return (
<button onClick={doStuff} type={type} disabled={disabled}>
{children}
</button>
)
};
I can see you do setTimeout(doStuff3, 500); inside of function that is referencing undefined function, you might want to define those in App.js and pass those as props to buttons

Related

I'm attempting to use boolean props: when the user clicks on the Selected button, the Select text should be hidden

and when the user clicks "Selected," show the Select,Please take a look at my code and tell me where I'm going wrong.
This is the App.js file I'm working on. 
import "./styles.css";
import MainShow from "./Show";
import { useState } from "react";
export default function App() {
var [isDone, setDone] = useState(false);
const Delected = () => {
setDone(!isDone);
console.log("set");
};
const Selected = () => {
setDone(!isDone);
console.log("Del");
};
return (
<div className="App">
<h1>Hello ,Problem Solver</h1>
<MainShow DoneMain={isDone} /> //imported
<button onClick={Delected}>Delected</button> //Delected button
<button onClick={Selected}>Selected</button> //Selected button
</div>
);
}
This MainShow file has the Main function.Look at my code on CodeSandbox
import React, { useState } from "react";
const Main = (props) => {
const [isDone] = useState(props.DoneMain);
console.log(isDone);
return (
<div>
<div>
<div
className="container"
style={{ display: isDone ? "block" : "none" }}
>
<p> Select</p>
</div>
<p>Hello</p>
</div>
</div>
);
};
export default Main;
When the user clicks on the "Deleted" button, I want "Select" to be hidden, and when the user clicks on "Selected," I want "Select" to be displayed. 
Check for state value changes and show/hide
const Delected = () => {
setDone(false);
console.log("set");
};
const Selected = () => {
setDone(true);
console.log("Del");
};
{isDone && <MainShow DoneMain={isDone} />}
Demo

Button onClick not firing in Reactjs

Buttons are not doing what they are supposed to do, adding to good, neutral, bad feedback.
Curiously, I added a default button that uses different syntax to add to bad, and it works. So there is something wrong with my "giveGoodFeedback" functions.
import React, { useState } from 'react'
const Button = (props) => {
return (
<button onClick={props.handleClick}>
{props.text}
</button>)
}
const App = () => {
// save clicks of each button to its own state
const [good, setGood] = useState(0)
const [neutral, setNeutral] = useState(0)
const [bad, setBad] = useState(0)
const giveGoodFeedback = () => {
setGood( good + 1 )
}
const giveNeutralFeedback = () => {
setNeutral( neutral + 1 )
}
const giveBadFeedback = () => {
setBad( bad + 1 )
console.log('Bad increases')
}
return (
<div>
<h1>give feedback</h1>
<Button text='good' onClick={giveGoodFeedback}/>
<Button text='bad' onClick={giveBadFeedback}/>
<Button text='neutral' onClick={giveNeutralFeedback}/>
<button onClick={() => setBad(bad + 1)}>
Click me
</button>
<h1>Statistics</h1>
<ul>
<li>good : {good}</li>
<li>neutral : {neutral}</li>
<li>bad : {bad}</li>
</ul>
code here
</div>
)
}
export default App;
Because you are using incorrect props, it should be props.onClick , please have a try. Thanks me later👍

How to add text based on click which is outside the Editor component , to the Editor

what I have tried ,
here i have added two button when user click value stores in state, than that state is passed to the editor , copy as a props . then I was trying to convert value to html code and then concat the copy prop then again convert to html to draft format, and then update the state, but i am not able to fix.
Codesandbox link : code
what i want when user click on button it should append with the text value in editor.
Able to add text based on clicked, but now problem is to append text based on cursor position , currently it adds to the end, i want to be added where the user points the cursor and then click the button it should be added there
Latest code : Updated code with add text functionality
Parent Component
import EditorWrapper from "./Editor";
export default function App() {
const [copy, setCopy] = useState("");
return (
<>
<div className="App">
<div className="d-flex">
<button
onClick={() => setCopy("Welcome")}
className="btn btn-primary me-2"
>
Welcome
</button>
<button
onClick={() => setCopy("Thank you")}
className="btn btn-primary"
>
Thank you
</button>
</div>
<EditorWrapper copy={copy} />
</div>
</>
Editor Component
import "./styles.css";
import React, { useState, useEffect } from "react";
import { Editor } from "react-draft-wysiwyg";
import { EditorState, ContentState, convertToRaw } from "draft-js";
import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
import htmlToDraft from "html-to-draftjs";
import draftToHtml from "draftjs-to-html";
export default function EditorWrapper({ copy }) {
const initialState = () => EditorState.createEmpty();
const [editorState, setEditorState] = useState(initialState);
const onChange = async (value) => {
// const data = draftToHtml(convertToRaw(value.getCurrentContent()));
// console.log(data.concat(`<p>${copy}</p>`));
// const contentBlock = htmlToDraft(data);
// const contentState = ContentState.createFromBlockArray(
// contentBlock?.contentBlocks
// );
// const updateState = EditorState.createWithContent(contentState);
setEditorState(value);
};
return (
<Editor
editorState={editorState}
toolbarClassName="toolbarClassName"
wrapperClassName="wrapperClassName"
editorClassName="editorClassName"
onEditorStateChange={(value) => onChange(value)}
stripPastedStyles
ariaLabel="draftEditor"
/>
);
}
Parent Component
import { useState } from "react";
import { EditorState, Modifier } from "draft-js";
import EditorComponent from "./Editor";
const App = () => {
const initialState = () => EditorState.createEmpty();
const [editorState, setEditorState] = useState(initialState);
const sendTextToEditor = (text) => {
setEditorState(insertText(text, editorState));
};
const insertText = (text, editorValue) => {
const currentContent = editorValue.getCurrentContent();
const currentSelection = editorValue.getSelection();
const newContent = Modifier.replaceText(
currentContent,
currentSelection,
text
);
const newEditorState = EditorState.push(
editorValue,
newContent,
"insert-characters"
);
return EditorState.forceSelection(
newEditorState,
newContent.getSelectionAfter()
);
};
const buttonValue = ["welcome", "Thank you", "react"];
return (
<div>
{buttonValue.map((i) => (
<button
className="btn btn-primary"
key={i}
type="button"
onClick={() => sendTextToEditor(i)}
>
{i}
</button>
))}
<EditorComponent
editorState={editorState}
setEditorState={setEditorState}
/>
</div>
);
};
export default App;
Editor Component
import { Editor } from "react-draft-wysiwyg";
import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
const EditorComponent = ({ editorState, setEditorState }) => {
const onChange = async (value) => {
setEditorState(value);
};
return (
<div>
<Editor
editorState={editorState}
toolbarClassName="toolbarClassName"
wrapperClassName="wrapperClassName"
editorClassName="editorClassName"
onEditorStateChange={(value) => {
onChange(value);
}}
stripPastedStyles
ariaLabel="draftEditor"
/>
</div>
);
};
export default EditorComponent;
Refer CodeSandbox

Click anywhere to close dropdown React

Hi I am creating an app where the user can search for books by title. The user can search and each book result has a dropdown. so I have many dropdowns on a single page (the search results page). I am trying to make a dropdown close when the user clicks outside of the dropdown button (which is a div). Currently I can open the dropdown by clicking on the dropdown button and only close it when clicking on the dropdown button again.
I need the dropdown to close when clicking anywhere except the dropdown options. How would I go about doing this?
ButtonDropDown.js
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { BsFillCaretDownFill } from 'react-icons/bs';
const ButtonDropDown = ({ choices, label }) => {
const [active, setActive] = useState(false);
const toggleClass = () => {
setActive(!active);
};
return (
<div className="dropdown">
<button onClick={toggleClass} type="button" className="dropbtn">
<BsFillCaretDownFill />
</button>
<div
id="myDropdown"
className={`dropdown-content ${active ? `show` : `hide`}`}
>
<div>{label}</div>
{choices.map((choice) => (
<div>{choice}</div>
))}
</div>
</div>
);
};
ButtonDropDown.propTypes = {
choices: PropTypes.arrayOf(PropTypes.string).isRequired,
label: PropTypes.string,
};
ButtonDropDown.defaultProps = {
label: 'Move to...',
};
export default ButtonDropDown;
Book.js
import React from 'react';
import PropTypes from 'prop-types';
import ButtonDropDown from './ButtonDropDown';
const Book = ({ title, authors, thumbnail }) => {
return (
<div className="book">
<img src={thumbnail} alt={title} className="book-thumbnail" />
<div className="book-title">{title}</div>
<div className="book-authors">{authors}</div>
<ButtonDropDown
choices={['Currently Reading', 'Want to Read', 'Read', 'None']}
/>
</div>
);
};
// Move to..., currently reading, want to read, read, none
Book.propTypes = {
thumbnail: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
authors: PropTypes.arrayOf(PropTypes.string),
};
Book.defaultProps = {
authors: [],
};
export default Book;
SearchPage.js
import React, { useEffect, useState } from 'react';
import { BsArrowLeftShort } from 'react-icons/bs';
// import { debounce } from 'debounce';
import SearchBar from '../components/SearchBar';
import { search } from '../api/BooksAPI';
import Book from '../components/Book';
const SearchPage = () => {
const [query, setQuery] = useState('');
const [data, setData] = useState([]);
// const [isLoading, setIsLoading] = useState(true);
const handleChange = (e) => {
setQuery(e.target.value);
};
useEffect(() => {
const bookSearch = setTimeout(() => {
if (query.length > 0) {
search(query).then((res) => {
if (res.length > 0) {
setData(res);
} else setData([]);
});
} else {
setData([]); // make sure data is not undefined
}
}, 1000);
// bookSearch();
// console.log(data); // undefined initially since we didnt search anything
return () => clearTimeout(bookSearch);
// if (data !== []) setIsLoading(false);
// setIsLoading(true);
}, [query]);
return (
<div>
<SearchBar
type="text"
searchValue={query}
placeholder="Search for a book"
icon={<BsArrowLeftShort />}
handleChange={handleChange}
/>
<div className="book-list">
{data !== []
? data.map((book) => (
<Book
key={book.id}
title={book.title}
authors={book.authors}
thumbnail={book.imageLinks.thumbnail}
/>
))
: 'ok'}
</div>
</div>
);
};
export default SearchPage;

How to send values React Hook(props)

I made My code.
When Click the button A, appear AAA.
Or Click the button B, appear BBB, Click the button C, appear CCC.
// Main > RightMain.js
import React, { useState } from 'react'
function RightMain() {
const [screen, setScreen] = useState('');
const A = () => {
setScreen('A')
}
const B = () => {
setScreen('B')
}
const C = () => {
setScreen('C')
}
return (
<div>
<button onClick={A}>A</button>
<button onClick={B}>B</button>
<button onClick={C}>C</button>
{screen === 'A' && <div>AAA</div>}
{screen === 'B' && <div>BBB</div>}
{screen === 'C' && <div>CCC</div>}
</div>
)
}
export default RightMain
And I wanna separate My Code(RightMain.js).
When I Click the Button on the RightMain.js.
The Result appear's on the Formations.js like the image below.
But I don kno how to bring value(RightMain.js's screen) to the Formations.js.
// Main > LeftMain.js
import React from 'react'
import RadioBtn from './LeftMain/RadioBtn';
import Formation from './LeftMain/Formation';
function LeftMain() {
return (
<div>
<div>
<RadioBtn />
</div>
<div>
<Formation />
</div>
</div>
)
}
export default LeftMain
//Main > LeftMain > Formation.js
import React, { useState } from 'react'
import RightMain from '../RightMain';
function Formation() {
return (
<div>
</div>
)
}
export default Formation
Thx
If I understand correctly, LeftMain and RightMain are sibilings, and Formation is a child of LeftMain.
One possible approach is to use Context API.
Something like this should work:
// Define the default value
// or return null and take that into consideration when using "useContext"
export const MyCurrentScreenContext = React.createContext({
setScreen: () => void 0,
screen: ''
});
export const MyCurrentScreenProvider = props => {
const [screen, setScreen] = useState('');
const value = useMemo(() => ({ screen, setScreen }), [screen, setScreen]);
return (
<MyCurrentScreenContext.Provider value={value}>
{props.children}
</MyCurrentScreenContext.Provider>
);
}
const Main = () => {
...
return (
<MyCurrentScreenProvider>
<LeftMain />
<RightMain />
...
</MyCurrentScreenProvider>
);
}
const RightMain() {
const { setScreen } = useContext(MyCurrentScreenContext);
....
};
const Formation() {
const { screen } = useContext(MyCurrentScreenContext);
....
};
Read more about context api at the official docs
From what I understand, you want to pass the values down to the child components. If that is correct then you could pass them as parameters when calling it and using props to receive them inside the child component. Something like this.
<div>
<RadioBtn randomVal="value" />
</div>

Categories

Resources