(REACT JS) put value on 1 array element from component - javascript

I'm trying to give one component the array value at a certain index and assign a value that i want from the child component.
I want it like this because I'm trying to do a survey app and the number of question can be different. this is just a little test that concludes what I want.
the base Component
import React, { useState } from 'react';
import './style.css';
import Comp from './Component.js';
export default function App() {
const [results, setResults] = useState([]);
results.length = 20;
results[3] = 'kiss';
results[2] = [12, 454, 45];
console.log(results);
return (
<div>
<h1>Hello StackBlitz!</h1>
<p>Start editing to see some magic happen :)</p>
<Comp result={results[5]}/>
<button onClick={() => console.log(results)}> SHOW </button>
</div>
);
}
the component
import React, { useState } from 'react';
const Comp = ({result}) => {
result = 1
console.log(result)
return (
<div>
hhhhh
</div>
);
}
export default Comp
here is a place I set it up => https://stackblitz.com/edit/react-mfpk5f?file=src%2FApp.js,src%2FComponent.js
every suggestion is highly appreciated!

parent componentHere i have tried a way to find solution ,
just keep a callback function in child component and call a function of parent component inside child so that u can pass data to it .
child component

If you want to add more, you use the setResults() e.g. setResults(['kiss']); so now your results='kiss', if you want more is setResults(...results,[12, 454, 45]); and now your results= kiss,12,454,45 . But:
import React, { useState } from 'react';
import './style.css';
import Comp from './Component.js';
export default function App() {
const [results, setResults] = useState(['hiii']);
function handleClick() {
const array1 = 'kiss';
const array2 = [12, 454, 45];
setResults([...results, array1, array2]);
console.log(results);
}
return (
<div>
<h1>Hello StackBlitz!</h1>
<p>Start editing to see some magic happen :)</p>
<Comp result={results[5]} />
<button onClick={() => handleClick()}> SHOW </button>
</div>
);
}
First you need to add the values when something happened, e.g. onClick={...}.
<Comp result={results[5]}/> this is correct, but you call when the result=[] show you need to call after updating, e.g.
import React, { useState } from 'react';
import './style.css';
import Comp from './Component.js';
export default function App() {
const [results, setResults] = useState(['Hi']);
function handleClick() {
const array1 = 'kiss';
const array2 = [12, 454, 45];
setResults([...results, array1]);
console.log(results);
}
return (
<div>
<h1>Hello StackBlitz!</h1>
<p>Start editing to see some magic happen :)</p>
<Comp result={results} />
<button onClick={() => handleClick()}> {results} </button>
<div>
{results.map(() => {
return <Comp result={results[5]} />;
})}
</div>
</div>
);
}
Of course this is NOT the best solution, but I hope you understand what happened, and like you will see you need to press the button 5 times to get something for the results[5] <Comp result={results[5]} />
and for the last you need to change the Comp:
import React, { useState } from 'react';
const Comp = ({result}) => {
const [compResults, setcompResults] = useState(result);
console.log(compResults)
return (
<div>
{compResults}
</div>
);
}
export default Comp

Related

How to pull specific data from an array?

I have created an array that gives a certain ID to each component every time it is added to the array. But now that the component is created, I want to be able to pull the data. Like the boxid or title when needed.
I currently am trying to make the value of <textarea /> in Todobox.jsx the unique boxid. But it does not seem to print a value.
Here is my code:
ElementContext.js:
import React, { createContext, useState } from 'react';
import Todobox from './components/Todobox';
export const ElementContext = createContext();
export const ElementContextProvider = ({children}) => {
const [elements, setElements] = useState([]);
const [elementId, setElementId] = useState(0);
const [refDict, setRefDict] = useState({});
const newElementId = (elements) =>{
setElementId(elementId + 1);
console.log(elementId)
}
const newElement = () => {
newElementId();
if (!refDict[elementId]) { //so if nothing in "refDict" that means the elementId is unique
setElements(prev => [...prev, { title: 'Placeholder', boxid: elementId }]);
setRefDict((prev) => ({...prev, [elementId]: true}));
}
console.log(elements);
};
const value = {
elements,
setElements,
newElement,
elementId
};
return(
<ElementContext.Provider value={value}>
{children}
</ElementContext.Provider>
)
};
HomePage.jsx:
import react from 'react';
import { useEffect, useContext } from 'react';
import '../App.css';
import Todobox from './Todobox';
import { ElementContext } from '../ElementContext';
export default function HomePage(){
const { elements, setElements, newElement, elementId } = useContext(ElementContext);
return(
<div className='page-container'>
<div className='header'>
<a className='header-title'>Trello Clone!</a>
<a className='header-button' onClick={newElement}>Create a list</a>
</div>
<div className='element-field'>
{elements.map((elements, elementId) => <Todobox key={elementId} />)}
</div>
</div>
)
}
Todobox.jsx:
import React from 'react';
import Item from './Item';
import { useContext } from 'react';
import '../App.css';
import { ElementContext } from '../ElementContext';
export default function Todobox(){
const { elements, setElements, newElement, elementId } = useContext(ElementContext);
return(
<div className='element-box'>
<a className='element-title'>PlaceHolder</a>
<Item />
<textarea
className='element-input'
type='text'
placeholder={elements.boxid}
/>
</div>
)
}
I am pretty new to react and such so any help is appreciated!
The elements array in state (and context) is an array of objects, and those objects have a boxid property. To use it, you need to reference or pass down that property when iterating over the elements. So your starting point would be to change this line:
elements.map((elements, elementId) => <Todobox key={elementId} />)
I'd change Todobox so that it doesn't use context at all, and is instead passed down all values it needs to render from the parent, including the boxid.
Other issues:
The .map callback parameter is not an array - it's a single object, so it should probably be called element, not elements, to avoid confusion
Keys should usually not be the index of the element in the array. Use a more unique identifier, such as the boxid, which will never change for a particular object. (In your current implementation, the elementId in the .map callback may not reflect the actual boxid of the object being iterated over, if you ever remove an item from the middle of the state array.)
elements.map((element) => <Todobox key={element.boxid} boxid={element.boxid} />)
export default function Todobox({ boxid }){
return(
<div className='element-box'>
<a className='element-title'>PlaceHolder</a>
<Item />
<textarea
className='element-input'
type='text'
placeholder={boxid}
/>
</div>
)
}

React useContext: State is displaying undefined

I'm passing the value of my state using useContext. However it keeps on saying that "toggle" is undefined how do i solved this part that the value of toggle can be passed to mainSection?
Here's my code
import React, { useState, createContext } from 'react';
import ReactDOM from 'react-dom';
const languages = ['JavaScript', 'Python'];
export const reactContext = React.createContext()
function App() {
const [toggle,setToggle] = useState(false)
// implement Context here so can be used in child components
return (
<reactContext.Provider value={{toggle,setToggle}}>
<MainSection />
</reactContext.Provider >
);
}
function MainSection() {
console.log(toggle)
return (
<div>
<p id="favoriteLanguage">Favorite programing language: {languages[0]}</p>
<button id="changeFavorite" onClick={() => console.log(toggle)}>Toggle language</button>
</div>
)
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
you are missing useContext. At the same time you should likely use ReactContext instead of reactContext.
function MainSection() {
const { toggle, setToggle } = useContext(reactContext) // <-- you are missing this line
console.log(toggle)
return (
<div>
<p id="favoriteLanguage">Favorite programing language: {languages[0]}</p>
<button id="changeFavorite" onClick={() => console.log(toggle)}>Toggle language</button>
</div>
)
}
Docs - https://reactjs.org/docs/hooks-reference.html#usecontext

React, passing state from a Child component to the Parent

I'm just learning React and ran into a problem. I'm making a bunch of counter components that look like this :
The problem is that I have defined the state in each of these counters which is 3 of them and I'd like to pass the value (number) into the parent so I can add it up and display the total count.
Here is my child counter component:
import React, { useState } from "react";
const Counter = () => {
const [count, setcount] = useState(0)
const handleIncrement=()=>{
setcount(count+1);
}
const handleDecrement=()=>{
setcount(count+-1);
}
return (
<div>
<button onClick={()=>{handleIncrement()}}>+</button>
<span>{count}</span>
<button onClick={()=>{handleDecrement()}}>-</button>
</div>
);
};
export default Counter;
And here is the parent which I want to pass my values to so I can add them up and show the total :
import React from 'react'
import Counter from './Counter'
const Counters = () => {
return (
<>
<h3>totalcount:</h3>
<Counter/>
<Counter/>
<Counter/>
</>
)
}
export default Counters
What I tried was to make multiple states but I can't get a good way to make this. I know there's an easy answer for this and I'm making it too complicated. If you guys have other optimization for my code please share.
In React state goes top to bottom. A nested component can update the state of a parent if a function defined in the parent has been passed to it as props. Which means, what you wanna do is not possible as your code is set up. A way to achieve what you are looking for is:
Pass setCounter down to each Counter instance as props, like so:
import React, { useState } from 'react'
import Counter from './Counter'
const Counters = () => {
const [countOne, setCountOne] = useState(0)
const [countTwo, setCountTwo] = useState(0)
const [countThree, setCountThree] = useState(0)
return (
<>
<h3>totalcount: {countOne + countTwo countThree} </h3>
<Counter count = {countOne} setCount = {setCountOne} />
<Counter count = {countTwo} setCount = {setCount} />
<Counter count = {countThree} setCount = {setCountThree} />
</>
)
}
export default Counters
Get setCounter from the props inside Counter and use it where you want:
import React, { useState } from "react";
const Counter = ({count, setCount}) => {
const handleIncrement=()=>{
setCount(count+1);
}
const handleDecrement=()=>{
setCount(count+-1);
}
return (
<div>
<button onClick={()=>{handleIncrement()}}>+</button>
<span>{count}</span>
<button onClick={()=>{handleDecrement()}}>-</button>
</div>
);
};
export default Counter;

getting problem on using useContext in react?

I have a simple react app in which i have to use useContext.
(btw im using vite + react)
here is my code for Context.jsx
import React, {useContext} from 'react';
const emailContext = React.createContext();
export const useEmail = () => useContext(emailContext);
export const emailProvider = ({children}) => {
const currentUser = "None";
const value = {
currentUser
}
return(
<emailContext.Provider value={value}>
{children}
</emailContext.Provider>
)
}
and heres how i am using the context
import "./styles.css";
import { useEmail } from "./Context/Context"
export default function App() {
const {currentUser} = useEmail();
return (
<div className="App">
<h1>Hello CodeSandbox {currentUser}</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
I am sure why I am getting error in this code.
some of the errors that I am getting
_useEmail is undefined (latest)
currentUser user is undefined
thing i have tried
Initialized createContext with some initial value (only intial value is visible).
using useContext() directy in the App.js (useContext(emailContext) return undefined)
instead of {children} used <children/>.
used useState instead of const currentUser in emailProvider
I am getting same problem even when I use typescript.
but none of the above helped.
You should wrapping app with <emailProvider></emailProvider> to using data in value={value}. Now it gets undefined from const emailContext = React.createContext();
Below code may help you analyse the flow , also check link for more details https://medium.com/technofunnel/usecontext-in-react-hooks-aa9a60b8a461
use useContext in receiving end
import React, { useState } from "react";
var userDetailContext = React.createContext(null);
export default function UserDetailsComponent() {
var [userDetails] = useState({
name: "Mayank",
age: 30
});
return (
<userDetailContext.Provider value={userDetails}>
<h1>This is the Parent Component</h1>
<hr />
<ChildComponent userDetails={userDetails} />
</userDetailContext.Provider>
);
}
function ChildComponent(props) {
return (
<div>
<h2>This is Child Component</h2>
<hr />
<SubChildComponent />
</div>
);
}
function SubChildComponent(props) {
var contextData = React.useContext(userDetailContext);
return (
<div>
<h3>This is Sub Child Component</h3>
<h4>User Name: {contextData.name}</h4>
<h4>User Age: {contextData.age}</h4>
</div>
);
}

How to trigger child component function

I am trying to reducing my code complexity to express by defining just skeleton code bellow. have to trigger the toggleModel of the child component
import React, { useState } from "react";
import "./styles.css";
const ChildComponent = (props) => {
// .... some useStates
const toggleModel = () => {
// have to trigger this methoud once user clicks on button
// have to change some states here
};
return (
<div>
{props.children}
...... other things .......
</div>
);
};
export default function ParentComponet() {
return (
<div className="App">
Hello
<ChildComponent>
<button
type="button"
onClick={() => {
// here i have to trigger the toggleModel function of ChildComponent
}}
>
Toggle Model
</button>
</ChildComponent>
</div>
);
}
i am rendering child component by sending children elements, have to trigger the toggleModel of the child component it will reduce my 70 % redundant code at our application. is there any way to achieve the same codesandbox. Thank you in advance
You can use useState and useEffect to pass state down and react to it.
import React, { useState } from "react";
import "./styles.css";
const ChildComponent = ({visible, children, setVisible}) => {
React.useEffect(() => {
const toggleModel = () => {
alert('Visible changes to ' + visible )
};
toggleModel()
}, [visible])
return <div>{children}</div>;
};
export default function ParentComponet() {
const [visible, setVisible] = React.useState(false)
return (
<div className="App">
Hello
<ChildComponent visible={visible} setVisible={setVisible}>
<button
type="button"
onClick={()=> setVisible(!visible)}
>
Toggle Model
</button>
</ChildComponent>
</div>
);
}
https://codesandbox.io/s/objective-ramanujan-j3eqg
The alternative is use #yaiks answer.
You can take a look at this question here, it can help you.
But I would say it's not a good practice to call a child function from the parent. Usually what I would do is to "lift up" the method to the parent, and pass down to the child if possible.
Here is another way to call your ChilComponent's function - using forwardRef:
import React, { useState, useImperativeHandle, forwardRef } from "react";
import "./styles.css";
const ChildComponent = forwardRef((props, ref) => {
useImperativeHandle(ref, () => ({
toggleModel() {
alert("alert from ChildComponent");
}
}));
return <div>{props.children}</div>;
});
export default function ParentComponet() {
return (
<div className="App">
Hello
<ChildComponent ref={ChildComponent}>
<button
type="button"
onClick={() => ChildComponent.current.toggleModel()}
>
Toggle Model
</button>
</ChildComponent>
</div>
);
}
Sandbox: https://codesandbox.io/s/pensive-jones-lw0pf?file=/src/App.js
My answer is courtesy of #rossipedia: https://stackoverflow.com/a/37950970/1927991

Categories