I am woking on a sample ReactJS application, where I want to pass a variable from one component to another.
class Layout extends React.Component{
constructor(props) {
super(props);
this.state = {keyword: ''};
}
render() {
return (
<div className="wrapper">
<Search />
<Listing />
</div>
);
}
};
ReactDOM.render(
<Layout />, app
);
In the above code, I want to pass a variable from <Search /> component to <Listing /> component.
Rlijo you'd pass props to components as follows:
<Search paramA={someParam} paramB={anotherParam} />
and to use the props within the Search component you'd call this.props.paramA (if using classes).
The way you've got the components setup, you wouldn't be able to share the state from the Search component (i.e. the object in this.state within Search) with the Listing component. There are libraries such as Redux designed to solve problems of shared state across components.
Props (or variables or params) flow downward so you'd need to provide shared props from a parent component. See you could provide this.state.keyword as a prop to both Search and Listing as these two components sit inside this parent component.
You can make it with function like
class Layout extends React.Component {
constructor(props) {
super(props);
this.state = {
keyword: '',
yourVariable: null
};
}
sendVariable(newValue) {
this.setState({ yourVariable: newValue });
}
render() {
return (
<div className="wrapper">
<Search onChange={this.sendVariable.bind(this)} />
<Listing sendValue={this.state.yourVariable} />
</div>
);
}
};
class Search extends React.Component{
render(){
let variable = "";
return <div onClick={this.porps.onChange(variable)}></div>;
}
}
Or use React-redux.
Related
I am attempting to create and render a functional component using the instructions here as a base. From what I've sen in there I should be able to do something along the lines of:
class MyComponent extends React.Component {
render() {
return (
<div>
<OtherComponent props="test" />
</div>
)}
function OtherComponent(props) {
return (
<div>
test
</div>
);
}
}
But this throws the error:
Unexpected token: function OtherComponent(props) {
^
I found a few posts that suggested removing the function so I tried that but then it throws the error:
OtherComponent is not defined
I'm able to get it working by creating a separate class component like so:
class OtherComponent extends React.Component {
render() {
But that's not what I want to do. What is the proper way to create/render a functional component in React.js?
For example this one works. See the docs ;)
React - Composing Components
function OtherComponent(props) {
return <div>test</div>;
}
class App extends React.Component {
render() {
return (
<div>
<OtherComponent props="test" />
</div>
);
}
}
Try this
class MyComponent extends React.Component {
OtherComponent = (props) => {
return (
<div>
test
</div>
);
}
render() {
return (
<div>
{this.OtherComponent("test")}
</div>
)}
}
You can't define a component inside of another component. A functional component means that the component is created from a function and is not a class. It can't have it's own state, because the state is initialized in class constructor. Check out this article for more info https://hackernoon.com/react-stateless-functional-components-nine-wins-you-might-have-overlooked-997b0d933dbc
const otherComponent = (props) =>
<div>
test
</div>;
Here is another way. Its not correct to declare a component in a render function. If it is used solely in a parent component why not make that explicit and use static
class MyComponent extends React.Component {
static myOtherComponent = (props) => <div>{'test'}</div>
render(){
return(
<div>
<MyComponent.myOtherComponent {props} />
</div>
)
}
The myOtherComponent behaviour is controlled purely through the props it gets , it won't have its own state.
Or you could just make it a separate component e.g
export default myOtherComponent = (props) => ()
and import it into MyComponent. Please note , now with hooks ( see React Docs ), you can use hooks to mimic state etc in functional components and the latter approach might be your cleanest and most flexible approach.
This way you can define a function component
function OtherComponent(props) {
return <div>{props}</div>;
}
And now you can use functional component in your App (class component) like below
class App extends React.Component {
render() {
return (
<div>
<OtherComponent props="test" />
</div>
);
}
}
My parent component
import EditReview from './partials/editReview'
class VenueDetails extends Component {
constructor(props) {
super(props)
this.child = React.createRef();
}
render() {
return (
<div className="place-review-text">
<EditReview {...this.props}/>
</div>
)
}
}
My child component
class EditReview extends Component {
onEditClick(review, editIndex) {
console.log('ppp')
}
render() {
const { handleSubmit, user, pristine, index, commentCrossClick } = this.props
return (
<div>
<Field
name="content"
component={renderTextArea}
className="form-control"
label="Write your review..."
rows={2}
/>
</div>
)
}
}
export default EditReview
I need to call onEditClick from the parent component. I tried this but doesn't work.
Kindly help me
Edit
After upgrade I am getting this
Error in ./~/react-dom/lib/ReactServerRendering.js
Module not found: 'react/lib/React' in /home/user/ashish/LTC/lovethesecities-frontend/node_modules/react-dom/lib
After resolving all the errors call child function from parent in react 16
React docs have a example of this using refs
https://reactjs.org/docs/refs-and-the-dom.html
I’m also wondering the use case of wanting to do this, maybe some context could help with an answer?
Try doing it like this:
import EditReview from './partials/editReview'
class VenueDetails extends Component {
render() {
return (
<div className="place-review-text">
<EditReview ref={Ref => this.child=Ref } {...this.props} />
</div>
)
}
}
and call the function in parent component as this.child.onEditClick(param1,param2)
EDIT1:
if you have to do it with react 15.x itself what you can do it is create the function in parent and pass it as a prop to child
I just creating a project and use a several component for a page and pass data by using props to each components. The problem is, when I have already change data from parent component to child component by using props and I have update the data from parent component, the child component still using the old data.
The example is just like this:
class Child extends Component{
constructor(props){
super(props);
this.state = {
variabel : props.variable
}
}
render() {
return (
<div>
<h1>{this.state.variable}</h1>
</div>
)
}
}
class Parent extends Component{
constructor(props){
super(props);
this.state = {
variabel : 'Hello'
}
}
render() {
return (
<div>
<Child variable={this.state.variable} />
</div>
)
}
}
So, when I run the page and update the variabel state in Parent Component, Child Component still show the old value. How to make it updated as the Parent Component data? Or I must using Redux for this case?
In general you'll only want to keep one particular piece of state in one place. If you reassign it in the constructor of Child, it will not update when the parent's state updates. So something like this pattern should work:
class Child extends Component{
// Note that no constructor is needed as you are not initializing any state or binding any methods.
render() {
return (
<div>
<h1>{this.props.variable}</h1>
</div>
)
}
}
class Parent extends Component{
constructor(props){
super(props);
this.state = {
variable : 'Hello'
}
}
render() {
return (
<div>
<Child variable={this.state.variable} />
</div>
)
}
}
A warning note about not initializing state with props is in the React docs for constructor, as a matter of fact.
Mitch Lillie's answer is the correct one. You should have only one source of truth.
In general, it's a good idea to keep the state in the nearest common ancestor of the components that depend on the state. Then you pass the props down.
If, however, you need to keep a copy of the prop in the child state, you should use the life cycles that React provides.
Codepen Live Demo
class Child extends React.Component {
constructor(props) {
super(props);
this.state = {
variable: props.variable,
};
}
componentDidUpdate(prevProps, prevState, snapshot) {
if (this.props.variable !== prevState.variable) {
this.setState({
variable: this.props.variable,
});
}
}
render() {
const varState = this.state.variable;
const varProps = this.props.variable;
return (
<div>
Child props: {varProps}
<br />
Child state: {varState}
</div>
);
}
}
class Parent extends React.Component {
constructor(props) {
super(props);
setInterval(this.updateTime, 1000); // refresh every second
this.state = {
variable: new Date().toLocaleString(),
};
}
updateTime = () => {
this.setState({
variable: new Date().toLocaleString(),
});
}
render() {
const time = this.state.variable;
return (
<div>
<div>
Parent: {time}
</div>
<Child variable={time} />
</div>
);
}
}
ReactDOM.render(
<Parent />,
document.getElementById('container')
);
Recently I learned how to pass props from one component to another. In my case, from <FileTree> to <TextBox>, as you can see here: https://codesandbox.io/s/y018010qk9
But after, I reorganized the code a bit and now it is possible to see the structure of my React App inside <App> (App.js). I decided to put the <FileTree> and <TextBox> side by side, with Bootstrap.
So, logically I thought that passing props from <App> to <TextBox> would be the same as I did before: From <FileTree> to <TextBox>. Unfortunatelly, it is not the case.
At the moment, this is the code inside <App>:
// Structure of the project
export class App extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<div className="col-md-12">
<SearchEngine />
</div>
<div className="col-md-6">
<FileTree />
</div>
<div className="col-md-6">
<TextBox content={this.props.activeNode} />
</div>
</div>
);
}
}
And here, the code inside <TextBox>:
// TextBox component
export class TextBox extends React.Component {
constructor(props) {
super(props);
this.state = {
content: 'Select A Node To See Its Data Structure Here...'
}
this.showContent = this.showContent.bind(this);
}
showContent (newContent) {
this.setState ({
content: newContent
})
}
componentWillReceiveProps (nextProps) {
this.setState ({
content: nextProps.content
})
}
render() {
return (
<div className="padd_top">
<div className="content_box">{this.state.content}</div>
</div>
);
}
}
export default TextBox;
Just in case, here one can find the <FileTree> component:
// Construction of FileTree
export class FileTree extends React.Component {
constructor(props) {
super(props)
this.state = {
activeNode: null
}
this.setActiveNode = this.setActiveNode.bind(this);
}
setActiveNode(name) {
this.setState({activeNode: name})
}
render() {
return(
<div className="padd_top">{
renderTree(
this.props.root || root,
this.setActiveNode,
this.state.activeNode
)
}
</div>
)
}
}
I'm recently getting to know React.js and I'm very thankful for any advice/clarity you can provide.
Thank you.
You need to use lift state method passing state from child to parent then from parent pass it to the child you want
In your parent component create a constructor with states then create liftStateUp function pass it to the child component that you want to receive the data from
constructor(props) {
super(props)
this.state = {
activeNode: '',
}
}
liftStateUp = (data) =>{
this.setState({ activeNode: data})
}
<div>
<div className="col-md-6">
<FileTree liftStateUp={this.liftStateUp} />
</div>
<div className="col-md-6">
<TextBox content={this.state.activeNode} />
</div>
</div>
Then in file_tree.js FileTree function you need to call liftStateUp function that we created it in the parent component
setActiveNode(name) {
this.setState({ activeNode: name });
this.props.liftStateUp(name);
}
https://reactjs.org/docs/lifting-state-up.html
Props are passed down from the parent component to child component. You need to work with global store so that you can interact with state in different siblings of components. For this, you may use redux.
If your application size is smaller, then you may also try using context api.
Hope, this helps to you.
Currently trying to learn React by making a simple application that grabs data from the openFEC API.
I currently have two components defined in my application, a SearchBar and a Candidate component. This is what my App.js currently looks like:
class App extends Component {
constructor(props){
super(props);
this.state = { candidate: [], searchTerm: '' }
}
render() {
return (
<div className="App">
<SearchBar />
<Candidate candidate={this.state.candidate}/>
</div>
);
}
}
export default App;
Problem: I need to update the Candidate component based on the data I receive from the API response. However, I'm making the API call in the SearchBar component and have no way of updating the candidate state defined in the App component.
Should I make the API call in the App component instead? If not, is there a way to send the data I get back from the SearchBar component into my App component?
I think the best way to do this is have the API call in your App Component, and pass that function down as a prop to your SearchBar Component. Your parent component (in this case, App) should be holding on to all of the relevant information and passing down to it's children what they need.
It should look something like this:
class App extends Component {
...
handleSearch(term) {
//handle fetch here
.then(res => this.setState({candidate: res})
}
render() {
<div className="App">
<SearchBar handleSearch={this.handleSearch}/>
<Candidate candidate={this.state.candidate}/>
</div>
}
}
In this way, you can achieve this
class App extends Component {
constructor(props){
super(props);
this.state = { candidate: [], searchTerm: '' }
this.triggerSearch=this.triggerSearch.bind(this);
}
triggerSearch(searchTerm){
this.setState({searchTerm})
}
render() {
return (
<div className="App">
<SearchBar trigerSearch=
{(searchTerm)=>this.triggerSearch(searchTerm)} />
<Candidate candidate={this.state.candidate}/>
</div>
);
}
}
export default App;
You can achieve it this way (without making API call from App).
class App extends Component {
constructor(props){
super(props);
this.state = { candidate: [], searchTerm: '' }
this.onDataReceived = this.onDataReceived.bind(this);
}
onDataReceived(data){
this.setState({ candidate: data });
}
render() {
return (
<div className="App">
<SearchBar onDataReceived={this.onDataReceived}/>
<Candidate candidate={this.state.candidate}/>
</div>
);
}
}
Roughly what happens here is:
You can see how I passed a function as a props to the SearchBar component via onDataReceived props.
You can invoke that function from within SearchBar component (e.g. make API call and call function passed as props with API results).
Invoking onDataReceived function will trigger setState
Calling setState will call render and now the Candidate component will receive more recent data from state.
More.