Limit the number of items in menu in react quizzes - reactjs

I am using react quizzes library:
https://codesandbox.io/s/react-quizzesexample-forked-2w1gj?file=/src/index.js:408-499
According to the documentation we can choose just these kind of builder items from menu that we want using toolBox.
I want to leave just Checkboxes in the menu but i didn't find a solution for this. Who can help?
function App() {
const [formdata, setFormData] = useState([]);
return (
<div className="App">
<QuizzBuilder onChange={setFormData} />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

This package react-quizzes, looks not really great. Its final build not include all modules, and require importing things directly. But if you want, here's the solution:
import React, { useState } from "react";
import ReactDOM from "react-dom";
import { QuizzBuilder } from "react-quizzes";
import ToolBox from "react-quizzes/lib/ToolBox";
import "react-quizzes/lib/assets/antd.css";
const filteredToolBox = ToolBox().filter(el => el.field_name === "checkboxes_")
function App() {
const [formdata, setFormData] = useState([]);
return (
<div className="App">
<QuizzBuilder toolBox={filteredToolBox} onChange={setFormData} />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Update #1
Added logic to override ToolBox label
import React, { useState } from "react";
import ReactDOM from "react-dom";
import { QuizzBuilder } from "react-quizzes";
import QuizExample from "./QuizExample";
import "react-quizzes/lib/assets/antd.css";
import ToolBox from "react-quizzes/lib/ToolBox";
import { defaultMessages } from "react-quizzes/lib/translations/TranslatedText";
const filteredToolBox = ToolBox().filter(
(el) => el.field_name === "checkboxes_"
);
const messages = {
en: {
...defaultMessages.en,
"toolbox.checkboxes.name": "Here are Checkboxes"
}
};
function App() {
const [formdata, setFormData] = useState([]);
return (
<div className="App">
<QuizzBuilder
messages={messages}
toolBox={filteredToolBox}
onChange={setFormData}
/>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Related

Join array with svg in jsx

I perform the following with jsx
import React from "react";
import ReactDOM from "react-dom";
import { ReactComponent as Img } from "./4ddd.svg";
import "./styles.css";
function App() {
return <div className="App">{[1, 2, 3].join(<Img />)}</div>;
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
This gives
The desired output is
What is the right way to join the array with svg icon?
Please see the code at codesandbox
join is expecting string join, but you're using a component, so that's why it shows [object Object]. You can do it with reduce instead
Sandbox
import React from "react";
import ReactDOM from "react-dom";
import { ReactComponent as Img } from "./4ddd.svg";
import "./styles.css";
function App() {
return <div className="App">{[1, 2, 3].reduce((current, value) => [current, <Img/>, value])}</div>;
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
I suggest you to use map instead of join in this way:
return (
<div className="App">
{[1, 2, 3].map((x) => (
<div className="Align">
{x}
{x !== [1, 2, 3].length && <Img />}
</div>
))}
</div>
);
And a little bit of css to keep all aligned:
.Align {
display: inline-block;
}
Here your codesandbox modified.
Another way:
import React from "react";
import ReactDOM from "react-dom";
import { ReactComponent as Img } from "./4ddd.svg";
import "./styles.css";
function App() {
const numberArr = [1, 2, 3];
return (
<div className="App">
{numberArr.map((item, index) => (
<>
{item}
{index < numberArr.length - 1 && <Img />}
</>
))}
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Here code: https://codesandbox.io/s/stupefied-drake-db64xk?file=/src/index.js:0-477

Why is the value not shown in react context?

Not sure why react context is not using the value passed in provider?
import { createContext } from "react";
const initialState = {
isOpen: false
};
export const alertContext = createContext(initialState);
export default (props) => {
return (
<>
<alertContext.Provider value={{ isOpen: true }}>
{props.children}
</alertContext.Provider>
</>
);
};
import "./styles.css";
import { useContext } from "react";
import AlertProvider, { alertContext } from "./AlertProvider";
export default function App() {
let value = useContext(alertContext);
return (
<div className="App">
<AlertProvider>
<pre>{JSON.stringify(value)}</pre>
</AlertProvider>
</div>
);
}
Why is the value for isOpen not true?
https://codesandbox.io/s/serene-faraday-1oib3?fontsize=14&hidenavigation=1&theme=dark
You need to wrap your provider around App in index.js
as shown:
import { StrictMode } from "react";
import ReactDOM from "react-dom";
import AlertProvider from "./AlertProvider";
import App from "./App";
const rootElement = document.getElementById("root");
ReactDOM.render(
<StrictMode>
<AlertProvider>
<App />
</AlertProvider>
</StrictMode>,
rootElement
);
and your app.js will look like this:
import "./styles.css";
import { useContext } from "react";
import { alertContext } from "./AlertProvider";
export default function App() {
let value = useContext(alertContext);
return (
<div className="App">
<pre>{JSON.stringify(value)}</pre>
</div>
);
}

check state of another functional component

i am new to react, i want to call the state of an outside function, for example :
export default function Child() {
const [succeeded, setSucceeded] = useState(false);
}
export default function Parent() {
if(Child.succeeded){
// do the following
}
}
i know that props are used for const objects only, and i don't want to merge both functions in a signle one to keep things organised, i would like to check for child's state to do the next step, or to callback the parent function with the new state to notify it. is there any way to do it ? Thanks a lot for your time.
Another approach is that you can use the useRef, which is very handy in some cases.
import React, {useState} from "react";
export default function Child({nameRef}) {
const [name, setName] = useState('');
React.useEffect(() => {
nameRef.current = name;
}, [name]);
return (
<>
<input nameRef={nameRef} type="text" onChange={event => setName(event.target.value)} />
</>
);
}
import React, { useState, useRef } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
import Child from './Child';
function App() {
let [name, setName] = useState("Nate");
let nameRef = useRef();
const submitButton = () => {
console.log(nameRef.current);
};
return (
<div className="App">
<p>{name}</p>
<div>
<Child nameRef={nameRef} />
<button type="button" onClick={submitButton}>
Submit
</button>
</div>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

React hook useState's setter inside function doesn't work

I'm trying to do a refactor of a countdown component that a project I'm working on has.
When I finished the migration of the logic the value of the counter didn't work. I decided to start from zero in codesandbox, so I tought of the simplest implementation and came out with this:
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function App() {
const [counter, setCounter] = useState(60);
useEffect(() => {
const interval = setInterval(() => setCounter(counter - 1), 1000);
return () => clearInterval(interval);
}, []);
return (
<div className="App">
<h1>Hello CodeSandbox {counter}</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App timerSeconds={360} />, rootElement);
What it happens here is that the value of counter stays on 59 after the first run of the interval.
Codesandbox: https://codesandbox.io/embed/flamboyant-moon-ogyqr
Second iteration on issue
Thank you for the response Ross, but the real issue happens when I link the countdown to a handler:
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function App() {
const [counter, setCounter] = useState(60);
const [countdownInterval, setCountdownInterval] = useState(null);
const startCountdown = () => {
setCountdownInterval(setInterval(() => setCounter(counter - 1), 1000));
};
useEffect(() => {
return () => clearInterval(countdownInterval);
});
return (
<div className="App" onClick={startCountdown}>
<h1>Hello CodeSandbox {counter}</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App timerSeconds={360} />, rootElement);
Add the counter variable within the second parameter (the array) of the useEffect function. When you pass in an empty array, it will only update the state once on the initial render. An empty array is often used when you're making an HTTP request or something along those lines instead. (Edited for second iteration)
import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function App() {
const [counter, setCounter] = useState(5);
const [counterId, setCounterId] = useState(null);
useEffect(() => {
return () => clearInterval(counterId);
}, []);
const handleClick = () => {
/*
* I'd take startCountdown and make
* it's own component/hook out of it,
* so it can be easily reused and expanded.
*/
const startCountdown = setInterval(() => {
return setCounter((tick) => {
if (tick === 0) {
clearInterval(counterId);
setCounter(0);
return setCounterId(null);
};
return tick - 1;
});
}, 1000)
setCounterId(startCountdown);
};
return (
<div className="App" onClick={handleClick}>
<h1>Hello CodeSandbox {counter}</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App timerSeconds={360} />, rootElement);
For more information on this implementation, read about React Hooks and skipping effects at https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects.
You can use the Functional Updates version of the function returned by useState to compute the new state based on the previous state.
Your updated code would look like this:
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function App() {
const [counter, setCounter] = useState(60);
useEffect(() => {
const interval = setInterval(() => {setCounter(counter => counter - 1);}, 1000);
return () => clearInterval(interval);
}, []);
return (
<div className="App">
<h1>Hello CodeSandbox {counter}</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App timerSeconds={360} />, rootElement);
UPDATE EDIT
Here is a version that starts the countdown with a click handler:
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function App() {
const [counter, setCounter] = useState(60);
const [countdownInterval, setCountdownInterval] = useState(null);
const startCountdown = () => {
setCountdownInterval(setInterval(() => setCounter(counter => counter - 1), 1000));
};
useEffect(() => {
return () => clearInterval(countdownInterval);
}, [countdownInterval]);
return (
<div className="App" onClick={startCountdown}>
<h1>Hello CodeSandbox {counter}</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App timerSeconds={360} />, rootElement);

Breadcrumb react code not working, how can i fix it?

So, I've tried setting up a component that creates breadcrumbs for React.
The code is here:
https://codesandbox.io/s/dreamy-microservice-mjxg2?fontsize=14
The error it's bringing back is that I'm mishandling the props.children.map, may any of you tell me why or how to fix it?
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
const Breadcrumb = ({props}) => {
const list = props.children.map((item) => (<li>{item}</li>));
return (
<ul>{list}</ul>
}:
const BreadcrumbItem = ({href, name}) => <div>{name}</div>;
function App() {
return (
<div className="App">
<Breadcrumb>
<BreadcrumbItem
href="/dashboard"
name="Dashboard"
/>
<BreadcrumbItem
href="/brand"
name="Brands"
/>
<Breadcrumb
href="/brand/new"
name="New brands"
/>
</Breadcrumb>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Change this:
const Breadcrumb = ({props}) =>
with
const Breadcrumb = (props) =>
Also, there is a typo in the App component. The last children is Breadcrumb, it should be BreadcrumbItem.
Working code is below:
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
const Breadcrumb = (props ) => {
const list = props.children.map(item => <li>{item}</li>);
return <ul>{list}</ul>;
};
const BreadcrumbItem = ({ href, name }) => <div>{name}</div>;
function App() {
return (
<div className="App">
<Breadcrumb>
<BreadcrumbItem href="/dashboard" name="Dashboard" />
<BreadcrumbItem href="/brand" name="Brands" />
<BreadcrumbItem href="/brand/new" name="New brands" />
</Breadcrumb>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Resources