Passing props from child function to parent function with React Native - javascript

Within Session() I want to access stateABC, which is in Item5().
The setup of my code looks like this:
Session.js:
function Session() {
//get handleRender(item).props.stateABC here
return (
<View>
{handleRender(item)}
</View>
);
}
handleRender.js:
export function handleRender(item) {
if(item == "Item5"){
return (
{Item5()}
);
}
}
Item5.js:
export function Item5() {
const [stateABC, setStateABC] = useState("123");
return (
....
);
}
I tried to get the value in Session() by using handleRender(item).props.stateABC, but all I get is an empty value.
Is it possible to receive properties from a function like that or are props only accessible in class components?
Any help is appreciated.
Thanks

If you need to access to stateABC value from Session component you have to pass a callback prop down from Session to Item5 and call it every time you update stateABC with setStateABC, passing the new value to the callback.
This is the simplest approach, you could also use React Context API or even something like Redux if you think that your app will grow in complexity.
Also, the approach that you tried to use is a bad idea. It works only in class component but in any case you should not use it, it's a bad thing to access props directly.

Related

How can I reuse a function with this.setState and other component function in react native?

I don't want to have a handle refresh function in every single screen in my project, so I created a Helper.js to handle this. This function has this.setState and another call for a function inside the screen component. This is what I got so far but it returns an error.
Exported function
export function handleRefresh(component) {
const {page, refreshing} = component.state
component.setState(
{
page:1,
refreshing:true
},
() => {
component.makeRemoteRequest();
}
);
};
and I call it in the component like this:
<FlatList
...
onRefresh={()=> handleRefresh(this)}
refreshing={this.state.refreshing}
...
/>
I saw that you can pass "this" as a param, but the error still says it is undefined.
setState shall be within that screen always where you are using FlatList because after making API you have to update and control the state of that screen.
All the states will be in the component where FlatList using.
Use case are not logical in my view. You can try to create a helper function which accepts different functions params like: page, isRefreshing and return the API response and also the API url and datapost will also be dynamic. Because you want to use it in many areas. It will be difficult to maintain.
So, If you like then use redux what you want.
https://snack.expo.io/#prashen/flatlist-onrefresh
You can do in this way.
class AComponent {
...
render() {
const thisComponent = this;
<FlatList
...
onRefresh={()=> handleRefresh(thisComponent)}
refreshing={this.state.refreshing}
...
/>
}
};
All this. uses refer a same class or function. Only use IF i'ts a child function, component or method.
I'ts don't work out of class function original, you can make a bridge for share data or status.
You can use redux for it and using stores for update screen state.

Cant change variable with callback function but console logging works

I am trying to change a variable in react with a callback function but cannot seem to do so. Here is my react component:
const MyComponent = () => {
let scenePinned;
const sceneCallback = event => {
if (event && event.state === 'DURING') {
console.log('Pinned');
scenePinned = true;
} else {
console.log('Not Pinned');
scenePinned = false;
}
};
console.log(scenePinned);
return (
<div>
<div style={scenePinned ? 'pinned' : 'not pinned'}/>
{(progress, event) => (
//Stuff Happens Here
), sceneCallback(event) )}
</div>
);
}
I am using react-scrollmagic and am trying to get the scenePinned variable to change from false to true and back to false again when scene is pinned to top. The console logging of Pinned and Not Pinned is happening correctly but I cannot seem to change the scenePinned variable. I am sure this is something very basic that I am not getting but I cannot understand why this is happening. Any help would be appreciated.
Note: I have tried using state to store the value but the callback is fired on scroll so the maximum depth is exceeded when trying to use state to store the scrolling status.
You need to use state for this. Otherwise the variable is reinitialized every time the component is rendered, and the value is lost.
console.log(scenePinned);
will run for the first time when the page loads
with react we use state the handle dynamic values.
or use rxjs
or create your own object and set listeners on it. with some custom event
so ex. with state
state={scenePinned:null}
then inside render method console.log(this.state.scenePinned)
A possible solution is to define a state variable in a parent component that will pass it to <MyComponent> as a prop.
Them move the sceneCallback function to the parent component and pass it as a prop to <MyComponent>
An explanation on how to define such a callback exists in many places. Here is one: (mine... ;) https://stackoverflow.com/a/55555578/5532513

setState inside a static method

I want to set the state of one component from another component using setState method as it seems to involve less coding, however I have come to know that I can't use the this keyword in a static method which has created a problem for me. I would like to know another get around of this problem. help would really appreciated.
First component
class First extends Component {
filterByLocation(loc) {
const filteredData = this.state.passedInfo.filter(({area}) => area === loc);
this.setState({members: filteredData})
}
}
Second component
class Second extend Component {
renderSuggestion() {
<TouchableOpacity
onPress = {()=> this.setState({location}, () => {
First.filterByLocation(this.state.location);
})}>
<Text> {"Click Me"}</Text>
</TouchableOpacity>
}
}
I initially considered this a comment, but really, it's an answer:
One component should never set the state of another component, even if it had access to the component instance (and thus to setState). It certainly can't do so without access to the component instance.
Instead:
Lift state up and have it passed to the component as props, or
Use portals and again pass the state as props (note: not entirely sure portals are supported in React Native, though a search turns up projects providing similar functionlity), or
Use context (which is supported in React Native)
...or possibly any of several other things. In your specific scenario, lifting state up seems like the right thing.
Why not to pass whole this object to your method like:
<TouchableOpacity
onPress = {()=> this.setState({location}, () => {
Home.filterByLocation(this, this.state.location);
})}>
<Text> {"Click Me"}</Text>
</TouchableOpacity>
Filter method:
filterByLocation(context, loc) {
const filteredData = context.state.passedInfo.filter(({area}) => area === loc);
context.setState({members: filteredData})
}
For sure it is not a good practice, it should solve the problem but should not be overused.

Passing value to parent in React component [duplicate]

I've created on form in child component. After submitting that form using jquery ajax method ($.ajax) I am retriving some data in json format. I want to put that data in my parent component's state. So, is there any method in react.js for passing value or data from child component to its parent component?
Thank you..
The way to do this without some kind of Flux implementation is to create a function on the parent element that handles the response/data from the child and pass that function as a prop. Then call that function from the child. Something like this:
Parent:
handleResponse(data) {
console.log(data)
}
render() {
return(
<div>
<Child handleResponse={this.handleResponse} />
</div>
);
}
then in the child:
handleAjax() {
$.get(url).then( (response) => {
this.props.handleResponse(response)
});
}
this all assumes ES6 syntax. Using ES5 you're going to have to use bind or var that = this to scope everything correctly.

Assigning a property with ES6 in a React Component

I am new to ES6 and still trying to grasp the concepts of the new specifications, i am currently working on a component in React where i need to make an ajax call and store this response in an object. Then use this object to the map the necessary elements
My component looks like the following
export class App extends Component {
search(){
//make ajax call
response = obj.responseText;
}
getValues(){}
render(){
let result = response.data.map(this.getValues);
return(
<div onKeyDown={this.search.bind(this)}>{result}</div>
)
}
}
How do i declare the "response" variable globally which gets assigned the data from ajax call "obj.responseText"?
It seems like you know what you want to achieve, but are a little confused about how to get there.
I would highly recommend reading the React documentation before you go any further.
Why not global variables?
How do I declare the response variable globally?
In short, don't. Global variables are well-documented as being evil. One instance of this component in a page with a global variable to store its search results would be fine, but imagine if you had two or more instances - they would all share/overwrite each other's search results.
Introducing state
Instead, you want to use React's component state functionality to store your search results.
You can set an initial state by setting a component's this.state in its constructor, (or in ES5, define a getInitialState method on the component).
Then, any time you want to update the component's state, you can call its this.setState(...) method, passing in a new state object. This will also trigger a re-render of the component.
Example
Here is a simple implementation following the above pattern:
export class App extends Component {
// Set the initial state of the component in the constructor
constructor(props) {
super(props);
this.state = {};
}
// This gets called when your component is mounted
componentDidMount() {
// Here we make our AJAX call. I'll leave that up to you
performMyAjaxMethodDefinedSomewhereElse(result => {
// We call this method to update `this.state` and trigger re-rendering
this.setState({ result });
});
}
render() {
// If we haven't received any results yet, display a message
if (!this.state.result) {
return (
<div>No results!</div>
);
}
// Iterate over the results and show them in a list
const result = this.state.result.map(text => (<li>{text}</li>));
// Display the result
return (
<ul>{result}</ul>
);
}
}
Naturally, if you don't want the AJAX call to fire off immediately, you can use a very similar approach, replacing componentDidMount with an event handler which looks almost identical.

Categories