Get another component input value React js - reactjs

I have two components one is app component and other one is sidebar component i have been using input field in side bar and i want to get the value of that input field in my app component on click how this could be possible ?

You can try lifting the state up.
Create a new component that will contain your two components. In that new component, create a function that you will pass as props inside the sidebar component.
class ContainerComponent extends React.Component {
constructor() {
super();
this.state = {
valueThatNeedsToBeShared: ''
}
}
handleChange(e) {
this.setState({valueThatNeedsToBeShared: e.target.value})
}
render() {
return (
<div>
<AppComponent value={this.state.valueThatNeedsToBeShared} />
<SidebarComponent handleChange={this.handleClick.bind(this)} value={this.state.valueThatNeedsToBeShared} />
</div>
)
}
}
const SidebarComponent = ({handleChange, value}) => <aside>
<input value={value} onChange={handleChange} />
</aside>
const AppComponent = ({value}) => <div>
value from sidebar: {value}
</div>

In pure react it is possible by adding callback from one component and use it into parent component to change their state and then send input value from parent's state to props of your second component

Related

Reactjs focus an input field located in a child component which is inside another child component

I am currently trying to focus an input field that is located in a child component which is inside another child component. consider the following,
Parent.js
child1.js
child2.js
I would like to focus input field in child2 when a button is clicked from parent.js.
I don't say using this technique it's good but you can achieve this by creating a setRef function who get pass by the child 1 to the child 2. Make sure to read this https://reactjs.org/docs/refs-and-the-dom.html why refs is not the best thing. For me I would use props callback.
But if you really want to use ref this is how you can do. I put the code example here. You can also play with the code here https://codesandbox.io/s/5x8530j3xn
class Child2 extends React.Component {
render() {
return (
<div>
<input ref={this.props.setRef} />
</div>
);
}
}
class Child1 extends React.Component {
render() {
return (
<div>
<Child2 setRef={this.props.setRef} />
</div>
);
}
}
class Parent extends React.Component {
setRef = ref => {
this.input = ref;
};
focus = () => {
this.input.focus();
};
render() {
return (
<div>
<Child1 setRef={this.setRef} />
<button onClick={this.focus}>Go Focus</button>
</div>
);
}
}
Just use plain vanilla JavaScript inside a React method.
handleFocus () {
document.getElementById('inputField').focus()
}
<button onClick={this.handleFocus}>My Button</Button>
This will focus the input after clicking the button.

Add a class to child component when parent component state changes

This is my first time attempting to build with React. I typically write UI interaction with jQuery or plain old JS. I simply want a text field which when there is text entered has a class added to it so that I can style it differently to the default state. Note I only want this class adding when there is at least one character entered, not when the field is focused.
I already have an onChange function in the child component which is used to change the state of 'textEntered' but I can't figure out how to make use of this state in the child component to add a class.
Here is my parent component
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import TextInput from './components/TextInput/TextInput';
export default class Form extends Component {
constructor(props) {
super(props);
this.state = {
textEntered: '',
completed: false,
};
}
render() {
return (
<div>
<TextInput
placeholderText={'Title'}
updateText={textEntered => this.setState({ textEntered })}
completed={this.state.completed}
/>
</div>
);
}
}
ReactDOM.render(<Form />, document.getElementById('react-create-form'));
And here is the child component
import React, { PropTypes } from 'react';
const TextInput = props => (
<div>
<input
type={props.type}
placeholder={props.placeholderText}
onChange={e => props.updateText(e.target.value)}
data-completed={props.completed}
/>
</div>
);
TextInput.propTypes = {
type: PropTypes.string,
placeholderText: PropTypes.string,
updateText: PropTypes.func,
completed: PropTypes.bool,
};
TextInput.defaultProps = {
type: 'text',
};
export default TextInput;
Pass the class name from parent component, and also put the check on that. If text field has atleast one character then pass the actual class name otherwise blank string.
Since you are storing the value of text field inside state of parent component so put the condition like this:
customClass = {this.state.textEntered.length ? 'actualClassName': ''}
Code:
<div>
<TextInput
customClass={this.state.textEntered.length ? 'actualClassName': ''}
placeholderText={'Title'}
updateText={textEntered => this.setState({ textEntered })}
completed={this.state.completed}
/>
</div>
Inside child component apply this customClass.
const TextInput = props => (
<div>
<input
type={props.type}
className={props.customClass}
placeholder={props.placeholderText}
onChange={e => props.updateText(e.target.value)}
data-completed={props.completed}
/>
</div>
);
Note: Another way is, pass the value in props instead of passing the class name and put the condition inside child component directly.

Render a component when another component is clicked

I want to render BlackSpark when RedSpark is clicked, but I'm not sure how to change the state of a component in another component. I know how to set state in the component itself, but how do I affect another component when I click a different component?
class BlackSpark extends React.Component {
render() {
return (
<div className="black"></div>
);
}
}
class RedSpark extends React.Component {
render() {
return (
<div className="red"></div>
);
}
}
class App extends React.Component {
render() {
return (
<div>
<BlackSpark />
<RedSpark />
</div>
);
}
}
In React, there's a concept of component composition as you've already embraced -- it allows you to accomplish what you want by rendering children based on the parent's state, another key concept known as lifting state up. What this means, is if you have mutually dependent components, create a single parent which composes them, and have state in the parent control the presentation and logic of the children. With the parent App, you can keep your state inside App, and based on App's state, conditionally render whatever you want -- either BlackSpark or both. For example, using the logical && operator:
{condition && <Component />}
This will only render <Component> when condition is truthy, or else it will not render anything at all (except for when condition is 0). Applying it to this situation, try adding state to your App component to utilize conditional rendering.
There's another key concept you need to understand: component props. They are essentially inputs to a component, certain properties passed to the component to tell how it should behave -- like attributes on regular HTML elements such as input placeholders, URLs, and event handlers. For example:
<Component foo="bar" bar={3} />
This will pass the props foo and bar down to Component with the values "bar" and 3 respectively and are accessible through this.props. If you were to access this.props.foo inside the Component component it would give you "bar". If you pair this up with composition, you can accomplish what you want:
class Example extends React.Component {
constructor() {
super();
this.state = {
showHello: true
}
this.handleChange = this.handleChange.bind(this);
}
handleChange() {
this.setState(prevState => ({
showHello: !prevState.showHello
}));
}
render() {
return (
<div>
{this.state.showHello && <Child2 />}
This is a test.
<Child1 onClick={this.handleChange} />
</div>
);
}
}
class Child1 extends React.Component {
render() {
return <div onClick={this.props.onClick}>Click me!</div>
}
}
class Child2 extends React.Component {
render() {
return <div>Hello!</div>
}
}
ReactDOM.render(<Example />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
The above example lifts state up by having a parent compose the children and maintain the state. It then uses props to pass down an onClick handler to Child1, so that whenever Child1 is clicked, the state of the parent changes. Once the state of the parent changes, it will use conditional rendering to render <Child2> if the condition is truthy. Further reading at the React documentation and on the logical && operator.
I know how to set state in the component itself, but how do I affect another component when I click a different component?
The recommended way to do it would be to create a parent component that has the state. You'd then use that state to determine when to render the other child component.
I want to render BlackSpark when RedSpark is clicked, but I'm not sure how to change the state of a component in another component. Also, what if I want to hide BlackSpark when GreenSpark is clicked and GreenSpark is inside BlackSpark?
In this case, here's how you'd do it.
const GreenSpark = ({ onClick }) => (
<button className="green" onClick={onClick}>X</button>
)
const BlackSpark = ({ onClick }) => (
<div className="black">
<GreenSpark onClick={onClick} />
</div>
)
const RedSpark = ({ onClick }) => (
<div className="red" onClick={onClick}></div>
)
class Spark extends React.Component {
constructor(props) {
super(props)
this.state = {
showBlack: false
}
this.boundShowBlack = this.showBlack.bind(this)
this.boundHideBlack = this.hideBlack.bind(this)
}
showBlack() {
this.setState({ showBlack: true })
}
hideBlack() {
this.setState({ showBlack: false })
}
render() {
return (
<div>
<RedSpark onClick={this.boundShowBlack} />
{this.state.showBlack && <BlackSpark onClick={this.boundHideBlack} />}
</div>
)
}
}

React - How do I access a function in another component?

My structure is as such:
<ParentComponent />
<Child 1 /> <Child 2 />
I have a function in <Child 1 />. Since <Child 1 /> controls the grid-layout, and <Child 2 /> is a Navbar with buttons, I want to have a button in <Child 2 /> which will reset some parameters in <Child 1 />.
How do I achieve this? As far as I can see, refs will only be able to go one "step" up the tree, not down.
There isn't any obvious way this function can be invoked from the parent component. Is there any way here? All the solutions I can think of aren't really following the React-mindset, namely the unidirectional data-flow.
You can make the parent component as a container for both components. So all the states and functions are handled in the parent components and pass them to the other components as props.
e.g.
class Parent extends React.Component {
constructor() {
super();
this.state = {
controls: controls
}
}
onClick = (dataFromChild2) => {
//Resetting
this.setState({controls: dataFromChild2})
}
render() {
return (
<div>
<Child1 gridControl={this.state.controls}/>
<Child2 onClick={this.onClick}/>
</div>
)
}
}
You can access the gridControl and onClick from this.props in the children components
UPDATE
Think of it this way, you have the Parent component with the states and function needed to handle the data. The children components take those data and update their states accordingly.
Let's Say the Parent Component is something like this:
class Parent extends React.Component {
constructor() {
super();
this.state = {
gridControl: {}
}
}
onChild2ButtonClick = (dataFromChild2) => {
this.setState({
gridControl: dataFromChild2
});
};
render() {
return (
<div>
<Child1 controls={this.state.gridControl}/>
<Child2 onClick={this.onChild2ButtonClick}/>
</div>
);
}
}
Child2 Component is something like this:
class Child2 extends React.Component {
constructor() {
super();
}
onClick = () => {
var data = {};
this.props.onClick(data);
};
render() {
return (
<div>
<button onClick={this.onClick}/>
</div>
);
}
If you're using states for Child1, and don't want to change them to props with function in the Parent component to handle them, then you update the state in the componentWillReceivePropsmethod with the new props received from the parent component, so that the props sent will match the states used in Child1 component.
Hope this will clear things up.
If your structure looks something as the following:
<ParentComponent>
<div>
<Child1 />
<Child2 />
</div>
<ParentComponent />
Both Child1 and Child2 should "communicate" through ParentComponent.
if Child2 will notify ParentComponent about a button click event then it can re-render Child1 with appropiate props accordingly or fire a function that Child1 gets as a prop. this is a basic flow in react.js
As an example consider a House component that has a Button and a Door child components. the Button will toggle opening and closing of the Door.
class House extends Component {
constructor(props) {
super(props);
this.state = {
isOpened: props.isOpened,
};
this.toggleOpenDoor = this.toggleOpenDoor.bind(this);
}
toggleOpenDoor() {
this.setState({
isOpened: !this.state.isOpened
});
}
render() {
return (
<div>
<Button onClick={this.toggleOpenDoor} />
<Door isOpened={this.state.isOpened} />
</div >
);
}
}
House.propTypes = {
isOpened: React.PropTypes.bool
};
House.defaultProps = {
isOpened: true
};
export default House;
On each change of this.state.isOpened the Door will re-render with the new value as prop
METHOD 1:
For this you need you need to maintain a store. On clicking button in your <Child2 /> component update the variable in the store. Read the updated variable in the store and if it has change update values in your <Child1 /> component. You can user either flux, redux, mobx etc.. as the store choices, but I would say you can start with redux.
METHOD2:
If you don't want to use store, keep a state in your <Parent /> and on button click in <Child2 /> update your state in parent through a callback function. Pass this state value as props to <Child1 /> and make changes if the prop is present.

Accessing refs in a stateful component doesn't work in React?

I'm currently trying to refactor the simple-todos tutorial for meteor using presentational and container components, but ran into a problem trying to access the refs of an input in a functional stateless component. I found out that to access refs, you have to wrap the component in a stateful component, which I did with the input.
// import React ...
import Input from './Input.jsx';
const AppWrapper = (props) => {
// ... more lines of code
<form className="new-task" onSubmit={props.handleSubmit}>
<Input />
</form>
}
import React, { Component } from 'react';
This Input should be stateful because it uses class syntax, at least I think.
export default class Input extends Component {
render() {
return (
<input
type="text"
ref="textInput"
placeholder="Type here to add more todos"
/>
)
}
}
I use refs to search for the input's value in the encompassing AppContainer.
import AppWrapper from '../ui/AppWrapper.js';
handleSubmit = (event) => {
event.preventDefault();
// find the text field via the React ref
console.log(ReactDOM.findDOMNode(this.refs.textInput));
const text = ReactDOM.findDOMNode(this.refs.textInput).value.trim();
...
}
The result of the console.log is null, so is my Input component not stateful? Do I need to set a constructor that sets a value for this.state to make this component stateful, or should I just give up on using functional stateless components when I need to use refs?
or should I just give up on using functional stateless components when I need to use refs?
Yes. If components need to keep references to the elements they render, they are stateful.
Refs can be set with a "callback" function like so:
export default class Input extends Component {
render() {
// the ref is now accessable as this.textInput
alert(this.textInput.value)
return (
<input
type="text"
ref={node => this.textInput = node}
placeholder="Type here to add more todos"
/>
)
}
}
You have to use stateful components when using refs. In your handleSubmit event, you're calling 'this.refs' when the field is in a separate component.
To use refs, you add a ref to where you render AppWrapper, and AppWrapper itself must be stateful.
Here's an example:
AppWrapper - This is your form
class AppWrapper extends React.Component {
render() {
return (
<form
ref={f => this._form = f}
onSubmit={this.props.handleSubmit}>
<Input
name="textInput"
placeholder="Type here to add more todos" />
</form>
);
}
};
Input - This is a reusable textbox component
const Input = (props) => (
<input
type="text"
name={props.name}
className="textbox"
placeholder={props.placeholder}
/>
);
App - This is the container component
class App extends React.Component {
constructor() {
super();
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(event) {
event.preventDefault();
const text = this._wrapperComponent._form.textInput.value;
console.log(text);
}
render() {
return (
<AppWrapper
handleSubmit={this.handleSubmit}
ref={r => this._wrapperComponent = r}
/>
);
}
}
http://codepen.io/jzmmm/pen/BzAqbk?editors=0011
As you can see, the Input component is stateless, and AppWrapper is stateful. You can now avoid using ReactDOM.findDOMNode, and directly access textInput. The input must have a name attribute to be referenced.
You could simplify this by moving the <form> tag into the App component. This will eliminate one ref.

Resources