Fired method on input with other component with event - javascript

its possible to fired event like on example :
const Tet = (props) => {
return (
<div>
<label>id:<input onChange= **FIRED RR METHOD** type="text"/></label>
</div>
);
}
And my component
class TContainer extends React.Component {
rr(obj, ev) {
console.log(obja, ev.target.value));
}
render() {
return (
<Tet lala={this.state.dataList} rr={this.rr.bind(this)}/>
)
}
How to call method with event.target.value and passing normal attr.

If you just want to propagate props, the easiest way to do it is:
const Tet = ({ onChange }) => {
return (
<div>
<input type="text" onChange={onChange} />
</div>
)
}
class TetContainer extends React.Component {
constructor() {
super()
this.handleChange = this.handleChange.bind(this)
}
handleChange(event) {
console.log(event.target.value)
}
render() {
return <Tet onChange={this.handleChange} />
}
}
ReactDOM.render(
<TetContainer />,
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>

If you want to pass custom arguments then pass a new function to onchange which call your rr function with your custom arguments like this
const Tet = (props) => {
return (
<div>
<label>id:<input onChange={(e) => {props.rr(obj,e)}} type="text"/></label>
</div>
);
}

Related

Lifting message up in REACT

I want to do a real time searching in React. How can I lift the message up from child to parent? Or how can I pass a parent handler to children through props to handle the event?
parent class:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
activities: activities,
filteredActivities: activities,
};
this.handleSearchChange = this.handleSearchChange.bind(this);
}
filterActivity = searchText => {
return this.state.activities
.filter(activity => {
if(activity.content.toLowerCase().includes(
searchText.toLowerCase())
){
return true;
}
return false;
});
}
handleSearchChange = event => {
this.setState({
filteredActivities: this.filterActivity(event.target.value)
});
};
render() {
const filteredActivities = this.props.filteredActivities;
return(
<div className="notificationsFrame">
<div className="panel">
<Header name={this.props.name} />
<SearchBar onChange={this.handleSearchChange} />
<Content activities={this.state.filteredActivities} />
</div>
</div>
);
}
}
Child class:
class SearchBar extends React.Component {
onChangeHandler = event => {
console.log(event.target.value);
}
render() {
return (
<div className="search-bar" >
<input type="text" onChange={this.onChangeHandler} />
</div>
);
}
}
I want to pass the event.target.value to handleSearchChange. if I put the code of class Searchbar to class App, I can perform a real time searching very good. But I can't put them into two components. I want to make them into two components. Thanks a lot.
Should be as simple as this:-
Child class:
class SearchBar extends React.Component {
onChangeHandler = event => {
this.props.inputChanged(event.target.value);
}
render() {
return (
<div className="search-bar" >
<input type="text" onChange={this.onChangeHandler} />
</div>
);
}
}
Parent class:
handleSearchChange = inputValue => {
this.setState({
filteredActivities: this.filterActivity(inputValue)
});
};
JSX of parent class:
<SearchBar inputChanged={this.handleSearchChange} />
since you're already passing the function's reference as a prop you can access it using this.props.propName and call it.
class SearchBar extends React.Component {
/* onChangeHandler = event => {
console.log(event.target.value);
} */
render() {
const { onChange } = this.props;
return (
<div className="search-bar" >
<input type="text" onChange={onChange} />
</div>
);
}
}
You can try this, as you already took event as a parameter in parent class for handleSearchChange method

Using dynamic onClick with ref

Passing a dynamic property of onClick= do something by the use of ref gives me back: TypeError: _this.listReference is null listReference is defined in one of my components that i will show below.
In Component #1
class Component1 extends Component {
constructor(props){
super(props)
this.listReference= null;
}
//Returns
<div>
<SomeComponent list={(ref) => this.listReference= ref} />
<Component2 onMarkerClick = {(index) => {
this.listReference.scrollTop = 48 * index
}}/>
In Component #2
render() {
const {classes, driversStore, onMarkerCLick} = this.props
...
{driversStore.sortedSelectedOrders.map((order , index) => {
return (
<Component3
onClick={ () => onMarkerClick(index)} />
In Component #3
render() {
const { onClick } = this.props;
return (
<div
onClick={onClick}>
I expect upon click to trigger the scroll functionality (as Stated in Component #1).
Thanks in advance!
Check this example. Hope it can help you!
const Component2 = (props) =>(
<button onClick={props.onClick}>click me</button>
);
const SomeCompo = (props) =>(
<div>SomeComponent</div>
);
class Component1 extends React.Component{
listReference = React.createRef();
render(){
return(
<div>
<SomeCompo list={this.listReference}>reference</SomeCompo>
<Component2 onClick={this.handleClick} />
</div>
);
}
handleClick = () => {
if(this.listReference){
this.listReference={scrollTop:100};
}
console.log(this.listReference)
}
}
ReactDOM.render(<Component1/>,document.getElementById("root"));
<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>
<div id="root"></div>
You should do the following in constructor,
this.listReference = React.createRef()

Reactjs button in Parent component which submits Redux Form in Child Component

I have 4 nested components, <CompD> is nested within <CompC> which is nested within <CompB> which is nested within <CompA>.
<CompD> contains a Redux Form with onSubmit={onSubmit} with a bunch of inputs and a Save button with type="submit"
A snippet of <CompD> currently with the button:
const propTypes = {
firstName: PropTypes.string,
secondName: PropTypes.string
};
const defaultTypes = {
firstName = " ",
secondName = " "
};
const PollForm = ({
firstName,
secondName
}) => (
<Form onSubmit={onSubmit}>
.
.
<button type="submit">
'Save'
</button>
</Form>
);
PollForm.propTypes = propTypes;
PollForm.defaultProps = defaultProps;
export default PollForm;
I want to move this button to <CompA> instead, so a button in <CompA> which behaves the exact same way as the button in <CompD> and submits the Form.
A snippet of <CompA> with a new button added:
const propTypes = {
onSubmit: PropTypes.func, ...
};
const defaultTypes = {
onSubmit: () = {}, ...
};
class Config extends Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this); ...
}
handleSubmit(data) {
this.props.onSubmit(data);
}
render() {
const {
} = this.props;
return (
.
.
<button onClick={onSubmit}>
'Save'
</button>
)
}
}
How do I pass the handleSubmit(data) function in <CompA the data from the form
Any ideas how I could do this?
You can lift up the form-submission state and logics from <CompD> to <CompA>, and may use the React Context to provide the form states and handlers deep-down to <CompD>, such as this:
import React from 'react';
import ReactDOM from 'react-dom';
const FormContext = React.createContext();
function CompB({ children }) {
return <div id="B">{children}</div>;
}
function CompC({ children }) {
return <div id="C">{children}</div>;
}
function CompD() {
return (
<FormContext.Consumer>
{({ onSubmit, onChange, name }) => {
return (
<form onSubmit={onSubmit}>
<label>
Name:
<input type="text" value={name} onChange={onChange} />
</label>
<input type="submit" value="submit-input" />
</form>
);
}}
</FormContext.Consumer>
);
}
class CompA extends React.Component {
onChange = ({ target: { value } }) => {
this.setState({ name: value });
};
onSubmit = event => {
event.preventDefault();
console.log('Submitting name: ', this.state.name);
};
state = {
name: 'defaultName',
onSubmit: this.onSubmit,
onChange: this.onChange,
};
render() {
return (
<FormContext.Provider value={this.state}>
<CompB>
<CompC>
<CompD />
</CompC>
</CompB>
<button name="submit" onClick={this.onSubmit}>submit-btn<button/>
</FormContext.Provider>
);
}
}
ReactDOM.render(
<CompA />,
document.getElementById('root'),
);
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>React App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
But it does looks verbose to have form separated from submit button. Not sure why you have such a need but normally it's better to keep them together in one component.
React Components use props to communicate with each other. Parent -> Child goes via props, Child -> Parent goes via callback props. Another way is to use new Context API. It would be better if you have a really deep nested structure.
Bellow I shown how it could be done via props.
class CompB extends React.Component {
state = {
name: "John Doe",
email: "john#doe.com"
}
handleChange = e => {
const {name, value} = e.target;
this.setState({[name]: value})
}
handleSubmit = e => {
e.preventDefault();
this.submit(this.state)
}
submit = (data) => {
console.log("submitted", data, +new Date());
this.props.onSubmit(data);
}
componentDidUpdate (oldProps) {
if (!oldProps.shouldSubmit && this.props.shouldSubmit){
this.submit(this.state);
}
}
render () {
const { name, email } = this.state;
return (
<form onChange={this.handleChange} onSubmit={this.handleSubmit}>
<div>
<label>
Name
<input name="name" type="text" value={name} />
</label>
</div>
<div>
<label>
Email
<input name="email" type="email" value={email} />
</label>
</div>
</form>
)
}
}
class CompA extends React.Component {
state = {
shouldSubmit: false,
}
submit = () => {
this.setState({shouldSubmit: true})
}
handleSubmit = () => {
this.setState({shouldSubmit: false})
}
render () {
const {shouldSubmit} = this.state;
return (
<div>
<CompB
shouldSubmit={shouldSubmit}
onSubmit={this.handleSubmit}
/>
<button
type="button"
onClick={this.submit}
>
Submit
</button>
</div>
)
}
}
ReactDOM.render(<CompA />, document.querySelector("#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>

ReactJS - How to change a component's state based on another component

Im trying to update a component's state when a different component's state changes.
Here is the main component that contains the form:
class IpsumForm extends React.Component {
state = {
character: 'All',
paragraphs: 1,
ipsumDisplayed: false
};
handleInputChange = (e) => {
const target = e.target;
this.setState({ paragraphs: target.value });
};
handleSelectChange = (e) => {
const target = e.target;
this.setState({ character: target.value });
};
handleReset = (e) => {
this.setState({
character: 'All',
paragraphs: 1,
ipsumDisplayed: false
});
};
handleSubmit = (e) => {
e.preventDefault();
this.setState({
ipsumDisplayed: true
});
};
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<p>Select Your Character:</p>
<select
value={this.state.character}
onChange={this.handleSelectChange}
name="characterPick"
>
<option value="All">All</option>
<option value="Michael">Michael</option>
<option value="Dwight">Dwight</option>
<option value="Jim">Jim</option>
<option value="Andy">Andy</option>
<option value="Creed">Creed</option>
</select>
<div className="length">
<p>How Many Paragraphs?</p>
<input
onChange={this.handleInputChange}
name="paragraphLength"
type="text"
/>
</div>
<hr />
<input
id="submit"
type="submit"
value="Bibity Boppity Give Me The Zoppity"
/>
<button onClick={this.handleReset}>Reset</button>
</form>
<br />
<IpsumText
person={this.state.character}
length={this.state.paragraphs}
displayed={this.state.ipsumDisplayed}
/>
</div>
);
}
}
export default IpsumForm;
And here is the component that I would like to return the ipsum within a textbox:
class IpsumText extends React.Component {
state = {
value: ''
};
handleValueChange = (e) => {
console.log(data.quote1);
this.setState({
value: data.quote1
});
};
render() {
let character = this.props.person;
let paragraphs = this.props.length;
let displayed = this.props.displayed;
return (
<div className="returned-ipsum">
<textarea value={this.state.value} onChange={this.handleValueChange} />
</div>
);
}
}
export default IpsumText;
The code I have now doesn't work because a state change from the IpsumForm doesn't cause the textarea onChange handler to run in the IpsumText
I'm wondering if there is a way to do this other than using a lifecycle method because it seems like i'm just overthinking it
Here's a very simple way of looking at it:
class App extends React.Component {
state = {
firstState: 1,
}
handleStateUpdate = () => {
this.setState(prev => ({
firstState: prev.firstState + 1
}))
}
render() {
console.log(this.state.firstState)
return (
<Foo handleStateUpdate={this.handleStateUpdate} />
)
}
}
class Foo extends React.Component {
state = {
otherState: 1,
}
handleLocalStateUpdate = () => {
this.props.handleStateUpdate()
this.setState(prev => ({
otherState: prev.otherState + 1
}))
}
render() {
return <button onClick={() => this.handleLocalStateUpdate()}>Click here!</button>
}
}
ReactDOM.render(<App />, document.getElementById('app'))
<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='app'></div>
What this is doing is passing down a function from the parent that updates the parent state, down to the child component. Once you define a function that updates the state of the child component, you can call that passed down function to also update the parent state.
Hopefully, the principle of doing this helps with the issue you're facing.
Here's a link to the code in case you wanna mess with it:
CodePen

ReactJS: This.props.toggleModal is not a function

I'm trying to access a parent method from a child to show a modal on screen and I'm getting the error: This.props.toggleModal is not a function. I'm passing the method down to the child so it can be called and using the correct state (I think). The button does call it's own method which in turn calls the parent. The modal component sits inside App.js.
App.js
class App extends Component {
constructor() {
super()
this.state = {
isOpen: false
}
}
toggleModal = () => {
this.setState({
isOpen: !this.state.isOpen
});
console.log('Open');
}
render() {
return (
<div className="App">
<Modal toggleModal={this.toggleModal} show={this.state.isOpen}
onClose={this.toggleModal}>
Here's some content for the modal
</Modal>
<div className="container">
<Header/>
<main>
<Route path="/users"
children={({ match, ...rest }) => (
<TransitionGroup component={firstChild}>
{match && <UserList {...rest} />}
</TransitionGroup>
)}/>
...
</main>
<Footer />
</div>
</div>
);
}
}
SearchBar.js - (located inside the user page)
class SearchBar extends Component {
constructor(props) {
super(props)
this.state = {
type: this.props.type,
value: ''
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.type !== this.props.type) {
this.setState({ type: nextProps.type });
}
};
handleClick = (e) => {
e.preventDefault();
console.log("Clicked!!!");
this.props.toggleModal();
};
handleChange = e => {
console.log(this.state.type);
this.setState({ value: e.target.value });
};
render () {
const isUser = this.state.type;
let rightContent = null;
if (isUser === "tour" || isUser === "venue") {
rightContent =
<div className="column">
<div className="float-right"><button className="add-new" onClick={this.handleClick}>Add New</button></div>
</div>
} else {
rightContent =
<div className="column">
<div className="float-right">
<div className="results-block">
<b>0</b>/<small>292</small>
</div>
</div>
</div>
}
return (
<div className="row main-search">
<div className="column">
<form action="">
<fieldset>
<label htmlFor="search">
<input type="text"
placeholder="Start typing..."
id="search-box"
onChange={this.handleChange}
value={this.state.value} />
</label>
</fieldset>
</form>
</div>
{rightContent}
</div>
)
}
}
export default SearchBar;
Check IF you getting toggleModal as props in your User Page Compoenent. If yes then pass it explicitly like to SearchBar
<SearchBar toggleModal = {this.props.toggleModal } /> // plus your rest of the props
You have to bind toggleModal with this in constructor so that use it as this.toggleModal.
EX.
this.toggleModal = this.toggleModal.bind(this);
check this ReactJs doc for more info.
https://reactjs.org/docs/handling-events.html

Categories

Resources