React - Transferring Data from Child to Parent - javascript

I'm building a react website and i'm stuck on a problem that has to do with passing data from a component, back to the App.js file.
so:
In my app.js file, i have a Router, that routes any request to path '/signin' to the Component. What i want to do, is i want to take a boolean from the component and store it in the app.js script, so that whenever that boolean is changed in the Component, it also changes on the app.js script.
Any suggestions on how i can do this? Any help at all would be appreciated!

the changeValue function will change the value in the App component. Since value is passed as props to ChildComponent, as soon as it changes, it will change in ChildComponent as well
const App = () => {
const [value, setValue] = useState('')
const changeValue = (value) => {
setValue(value)
}
return (
<div>
<ChildComponent
changeValue={changeValue}
value={value}
/>
</div>
)
}
const ChildComponent = ({changeValue, value}) => {
return (
<div>
<p>{value}</p>
<input
type='text'
onChange={(e) => changeValue(e.target.value)}
/>
</div>
)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Store the state at the parent level, and pass down the modifier function to the child via props or context.

Related

Access a function from a Component in another Component in React

I am totally blank on how to use a function that is inside a component and needs to be used in another component.
Here is a simple program:
Test.js
export default function Test(){
const testFunc = () => {
console.log("it is working")
}
return(
<div>
Hi
</div>
)
}
Test2.js
export default function Test2(){
return(
<button onClick={}> // Here I want to use testFunc() from Test file
Click
</button>
)
}
Could someone please explain how can it be achieved to access the function in Test2 file.
Thanks in advance!!
You will want to pass the function as a prop to the child component. You can't or I should say shouldn't pass a prop to a parent, you can do this but is not a react way and never recommended. What you would do in this case is but the logic in the parent because both siblings are needing access to it.
const App = () => {
const clickHandler = () => {
alert("Click event")
}
return (
<div className="App">
<ChildOne clickHandler={clickHandler}/>
<ChildTwo clickHandler={clickHandler}/>
</div>
)
}
}
You can either pass it down from a parent component, shown below, or you can use a custom hook
Parent Component:
import Child from './Child.js'
export default function Parent() {
const functionToBePassed = () => { ... }
return (
<Child func={functionToBePassed}>
)
}
Or you can do it via a custom hook
Two files, first one is the hook
export default function useFunc() {
const functionToBeShared = () => {...}
return { functionToBeShared }
}
//this is any component that wants to use the hook
import useFunc from ./useFunc;
export default function ComponentThatUsesHook() {
const {functionToBeShared} = useFunc();
}
Welcome to the React community.
To use a function that is inside a component and needs to be used in another component.
You need a common parent, that handles the function.
Let's say you have the following structure.
export const ParentComponent = () => {
return <>
<Test1 />
<Test2 />
<>
}
If you want some function in Test1 to affect Test2, then you do what in react is called lifting state up https://reactjs.org/docs/lifting-state-up.html
ParentComponent
export const ParentComponent = () => {
const [value, setValue] = useState('')
return <>
<Test1 setValue={setValue} />
<Test2 value={value} />
<>
}
Test1
export const Test1 = (props) => {
return <>
<input onChange={(e) => props.setValue(e.target.vale} />
<>
}
Test2
export const Test2 = (props) => {
return <p>{props.value}</p>
}
When a component renders another component, it is called the parent of the rendered child. Imagine React as a tree data structure where the App.tsx/jsx will be the tree's root.
Inspecting the code above, we can see that we have a function held in the parent. This is the function you would probably consider putting in Test1. However, if you need to use it in another component, that is not a child of the current element. You will need to find the nearest common parent and pass the functionality down like in the example above.
I hope it makes sense. If not, I recommend glancing at the Main Concepts part of the official React documentation. https://reactjs.org/docs/getting-started.html
As Konrad said in the comments, this can't be possible since these 2 components lack no relationship (Neither Components are rendering or calling each other within)
Something you could do is Render the Test2.js component within Test.js and add a callback like so:
Test.js
import Test2 from '...';
export default function Test(){
const testFunc = () => {
console.log("it is working")
}
return(
<div>
Hi
<Test2 callbackProp={testFunc} />
</div>
)
}
Test2.js
export default function Test2({callbackProp}){
return(
<button onClick={() => {callbackProp();} }> // Here I want to use testFunc() from Test file
Click
</button>
)
}
Now whenever Test.js is rendered, it will also render Test2 (Since Test is rendering a Test2 Component) but whenever you click the button within Test2, it will execute the callback which is a function passed from Test
Nonetheless though, it's impossible to call any functions from another Component without passing down a prop like this (for future reference)
Solution
Usually, context is used to share the same state between many components that aren't in parent-children relations.
codesandbox
Creating context
First, create a context:
const MyContext = createContext();
And context provider:
const MyContextProvider = ({ children }) => {
const [myState, setMyState] = useState(0);
return (
<MyContext.Provider value={{ myState, setMyState }}>
{children}
</MyContext.Provider>
);
};
And context hook (for convenience):
const useMyContext = () => useContext(MyContext);
Using context
Remember to use the provider in the common ancestor of the components:
function App() {
return (
<MyContextProvider>
<Component1 />
<Component2 />
</MyContextProvider>
);
}
Create your components:
function Component1() {
// as you can see, you can access the function here
const { setMyState } = useMyContext();
return (
<button onClick={() => setMyState((state) => state + 1)}>click me</button>
);
}
function Component2() {
// and the value here
const { myState } = useMyContext();
return myState;
}

Props are not passing from parent to child components in React Functional component

Hi developers I'm just a beginner in React.js. I tried to print props by passing from parent to child.
This is app.js file
import React from "react";
import Hooks from "./components/ReactHooks1";
import Hooks2 from "./components/ReactHooks2";
const App = () => {
return (
<div>
<h1>
Welcome to React App
</h1>
<Hooks2 title2={"Welcome"}/>
</div>
)
}
export default App
This is child component file
import React from 'react';
const Hooks2 = (props) => {
console.log(props);
}
export default Hooks2;
I just try to print props but it shows an empty object. what am I doing wrong please help me on this
You should return something or null to parent component from child, when you're using it in parent component. This will solve your problem
export const Hooks2 = (props) => {
console.log(props);
return <></>;
}
#Rasith
Not sure why would you want to do this, but if you're trying to pass a child component that would print something to the console. In this case you need to destructure the component's props. Here's an article about it from MDN.
This is how I would do it:
const CustomComponent = ({title}) => {
console.log(title)
}
const App = () => {
return (
<>
<h1>Hello World</h1>
<CustomComponent title={"Welcome"}/>
</>
);
};
For the title to be printed to the console, no need to add a return statement to the child component. Again, not sure why you would do this, but there you go.
Well trying to console.log title certainly would not work because what you are passing is called title2. Also your child component is not returning anything.
First, you have to return anything from your child component( even a fragment )
You can access title2 in the child component with any of these methods:
1- using props object itself
const Hooks2 = (props) => {
console.log(props.title2);
return;
}
2- you can also destructure props in place to access title2 directly
const Hooks2 = ({title2}) => {
console.log(title2);
return ;
}
You have to use destructuring in your ChildComponent, to grab your props directly by name:
const Hooks2 = ({title2}) => {
console.log(title2);
}
You can read a little bit more about it in here: https://www.amitmerchant.com/always-destructure-your-component-props-in-react/

React JS: How to pass variable from one file to another file, which is not parent or child of the same?

import moment from "moment";
import TrackerByDate from "./traker_by_date/tabs";
export default function Calender() {
const [value] = useState(new Date());
const [show, setTracker] = useState(false);
const [dateState, setDateState] = useState(new Date());
const changeDate = (e) => {
setDateState(e);
};
var pikerdate = moment(dateState).format("YYYY-MM-DD");
function clickTracker(e) {
setTracker(!show);
}
return (
<>
{show ? <TrackerByDate dataFromParent={pikerdate} /> : null}
<div style={{ width: "260px" }} className="res-calendar">
<Calendar
className={["c1", "c2"]}
onChange={changeDate}
onClickDay={clickTracker}
value={dateState}
/>
</div>
</>
);
I am trying to pass 'pikerdate' to a js file called diet.
callander.js and diet.js are not parent or child
I want to get a date in diet.js when the date is clicked on callender.js
To provide the best answer here we need to consider the relationship between both components.
For instance, if both components are ultimately rendered by a single parent component, then a simple and convenient way to manage this would be to simply move the state to the parent and pass it as props to the child components along with the setState method or dedicated functions to handle the relevant logic.
Example:
function Parent() {
const [state, setState] = useState();
return (
<A state={state} setState={setState} />
<B state={state} setState={setState} />
)
}
However, if that is not the case and the relationship between them is more complex,
then you likely need to manage some global state.
This can be achieved via React's built-in Context Api or via third party state managment libraries such as Redux or xState.
you can do it by taking "pikerdate" in the parent component where there two components(called and diet) are children like in App.js or some other component and pass "pikerdate" to both components.

function declared with const uses the old value of useState

I have a React component (functional) that contains a child component modifying the state of the parent component. I am using the hook useState for this.
After the state change, there is a "Next" button in the parent component that executes a function referencing the updated state. The problem is this next function uses the old state from before the state was modified by the child component.
I can't use useEffect here as the function needs to execute on the click of the "Next" button and not immediately after the state change. I did some digging about JavaScript closures, but none of the answers address my specific case.
Here's the code
const ParentComponent = () => {
const [myState, setMyState] = useState(0);
const handleNext = () => {
console.log(myState); // prints 0 which is the old value
}
return (
<ChildComponent modifyState = {setMyState} />
<Button onClick={handleNext} > Next </Button>
)
}
export default ParentComponent;
BTW there are no errors.
It's a little difficult to understand without your ChildComponent code. setMyState suggests that you need to update the increase the state by one when you click the next button, but you can't do that without also passing in the state itself.
An easier (imo) solution is to pass a handler down to the child component that is called when the next button is clicked. The handler then sets the state.
const {useState} = React;
function ChildComponent({ handleUpdate }) {
function handleClick() {
handleUpdate();
}
return <button onClick={handleClick}>Click</button>
}
function Example() {
const [myState, setMyState] = useState(0);
function handleUpdate() {
setMyState(myState + 1);
}
function handleNext() {
console.log(myState);
}
return (
<div>
<ChildComponent handleUpdate={handleUpdate} />
<button onClick={handleNext}>Next </button>
</div>
)
}
// Render it
ReactDOM.render(
<Example />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>
try to modify like this
<ChildComponent modifyState={(value) => setMyState(value)} />

Access input value in ReactDOM.render

I need to get input field's value inside a click handler inside ReactDOM.render().
The code inside App.js is
<input ref={node => {
this.todoInput = node
}} className="pull-left" />
<button onClick={this.props.addTodo}>Add Todo</button>
index.js
ReactDOM.render(<App
todos={store.getState().todos}
addTodo={() => {
console.log(this.refs);
//store.dispatch({
// type: 'ADD_TODO',
// id: nextTodoId++,
{/*text: this.refs.todoInput.value*/}
{/*});*/}
{/*this.refs.todoInput.value = '';*/}
}}
/>,
document.getElementById('root'));
Inside addTodo function , how can I access my refs object? Or ultimately to get todoInput's value
Update - One of the answers provided below works for me as an alternative solution. However, the reason what is bugging me is simple. I render App component inside of the ReactDOM.render(). Shouldn't App directly have access to it's input field as it is through some mechanism ?
In your code, you refer the todo inside addTodo function like this.refs.todoInput. Here this refers to the current instance where you are rendering ReactDOM.render.
So your input which is inside the app instance cannot be accessed in a different instance.
If you wanna access it your way then you need to add a ref to your app like this
ReactDOM.render(<App
ref={appInstance => { this.appInstance = appInstance;} }
todos={store.getState().todos}
.....
Now you can access the input inside app instance like below
addTodo={() => {
// your value from todoInput will be here..
const value = this.appInstance.todoInput.value;
}}
I suggest you to make App a stateful component and then you could pass on the ref or the value of the ref to the this.props.addTodo function.
Example code:
class App extends React.Component {
handleClick() {
this.props.addTodo(this.todoInput.value);
}
render() {
return (
<input ref={node => { this.todoInput = node }} className="pull-left" />
<button onClick={this.handleClick.bind(this)}>Add Todo</button>
)
}
}

Categories