In my React Native app I have a custom component that wraps a TextInput. In the code that uses the custom component, I want to call .focus() on the TextInput. I tried calling it directly on the custom component like this:
<CustomComponent
ref={ref => {
this.customComponent = ref;
}}
/>
this.customComponent.focus();
but I can't because, I assume, custom components don't have a focus() method. I could find a way to call it on the wrapped TextInput, but I'm wondering if there's a way to call it directly on the custom component.
Does anyone know how I can approach this?
if a class component you could use CustomComponent.prototype.yourFunction()
youFunction uses ref to call focus() on TextInput
If CustomComponent is your own component then in that case you can pass the ref via Forwarding Refs :
Here I have created sample code snippets, which has input inside CustomComponent and we can access ref inside that component via React.forwardRef((props, ref)
Then we have createRef from parent component and pass ref like <CustomComponent ref={this.ref}>.
Hope this will help you.
const CustomComponent = React.forwardRef((props, ref) => (
<div>
<input type="text" ref={ref} />
</div>
));
class App extends React.Component {
constructor(props) {
super(props);
this.ref = React.createRef();
}
componentDidMount() {
if(this.ref.current) {
this.ref.current.focus();
}
}
render() {
return (
<div>
Get Focused :
<CustomComponent ref={this.ref} />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('react-root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react-root"></div>
Related
import SomeComponent from 'Somewheere';
class MyPage {
render() {
return '<OtherComponent AcceptsSomeClass={SomeComponent} />';
}
}
in OtherComponent I want to be able to do
class OtherComponent {
render() {
return <this.props.AcceptsSomeClass open={true} someOtherProp={123}/>;
}
}
I want to be able to render SomeComponent inside OtherComponent. I know I can just pass a node or a function. But I've seen a library before that accepts a class like this and I want to pass the class so that I can control it more in OtherComponent instead of deciding how it renders in MyPage and passing it thee node/function.
In other words I want to pass a class (react component) as a prop and then be able to use it in the JSX.
What I did is that we are passing a function that renders a component, then we can call that function inside the OtherComponent to render it there.
class MyPage extends React.Component {
render() {
return <OtherComponent AcceptsSomeClass={() => <SomeComponent />} />
}
}
class OtherComponent extends React.Component {
render() {
return (
<div>
<p>Content inside OtherComponent</p>
{this.props.AcceptsSomeClass()}
</div>
)
}
}
class SomeComponent extends React.Component {
render() {
return <h1>HELLO WORLD!</h1>
}
}
ReactDOM.render(<MyPage />, 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>
An example of which you can pass components as props is when you are dealing with HOC (higher-order-components)
I use HOC to handle HTTP requests, for instance, using a modal to pop up on the screen with the loading / error when fetching /putting data, or authentication.
I will present you with a simple example:
import React from 'react'
import Modal from 'modal' //this would be a modal covering the screen
const httpHandler = WrappedComponent => {
const wrappedComponent = props => {
//handle some logic here, coded here, or as a result from some middleware
return (
<Fragment>
<Modal>...</Modal> //handle the HTTP async stuff here, like loading,
//or authentication, or an error message
<WrappedComponent {...props} />
</Fragment>
)
}}
You can call this inside a Component like this when you export another component
//all of the component stuff above
export default httpHandler(WrappedComponent)
I have 3 components which is my site. Each component js-file is loaded and all 3 shows on one page like this:
Topmenu
SectionOne
SectionTwo
In the Topmenu component I have a menu only. I’ve tried to setup the scrollToComponent onClick at a menu field (SectionOne). But I cannot figure out how to get it to scroll to SectionOne when clicked?
I know this.sectionOne is a ref to an internal ref, right? But how to direct it to a ref inside the “sectionOne.js” file?
I have the following inside my TopMenu.js file
onClick={() => scrollToComponent(this.sectionOne , { offset: 0, align: 'top', duration: 1500})}
To forward the ref to somewhere inside the component, you can use the logic of forwardRef.
This means that we create the ref in the parent component and pass the same to the component which passes it down to DOM element inside it.
class App extends React.Component {
constructor(props) {
super(props);
this.section1 = React.createRef();
this.section2 = React.createRef();
this.scrollToContent = this.scrollToContent.bind(this);
}
scrollToContent(content) {
switch(content) {
case 1:
this.section1.current.scrollIntoView({behavior: 'smooth'});
break;
case 2:
this.section2.current.scrollIntoView({behavior: 'smooth'});
}
}
render() {
return (
<main>
<Menu goTo={this.scrollToContent} />
<div className='main'>
<Section1 ref={this.section1} />
<Section2 ref={this.section2} />
</div>
</main>
);
}
}
and then, inside Section1,
const Section1 = React.forwardRef((props, ref)=>{
return (
<section ref={ref} className='section'>
<p>Section 1</p>
</section>
);
});
You can see a working sample here
I'm not using scroll-to-component package, but the same thing applies.
Forward Refs are supported only in React 16.3 now, you can use this alternative approach if you need the feature in lower versions.
Is there a way to expose a function of a React component?
class MyComponent extends Component {
someFunction() {
// I'd like to expose this function
}
render() {
return(
<div>Hello World</div>
);
}
}
In the above example, I'd like to expose someFunction() so that I can call it from the parent component.
In other words, I'm trying to call a function of a sub-component from the parent component.
Two questions:
Can I do this? If so, how?
This may be a more important question: Should I be doing this? I'm always mindful that something I may need now may be exposing an architectural flaw. So, I want to know if I should even be calling a sub-component's function from the parent component.
While it is possible to call a function on a child component, I don't think it would be idiomatic.
If you want to change the way a component renders, you should alter its props and trigger a re-render.
Keeping the interface for a component exclusively through the props helps to better encapsulate the inner workings of the component.
For your specific example, I would rather have a visible toggle that you alter and let the datePicker component decide for itself what it wants to do with that property value.
Can I do this?
Yes, We can achieve that by using ref, assign ref to MyComponent when rendering inside parent component then use that ref to call the function.
How?
Check this snippet:
class Parent extends React.Component {
_callChildComponent(){
this.child.someFunction();
}
render() {
return(
<div>
<div onClick={() => this._callChildComponent()}>Call</div>
<MyComponent ref={el => this.child = el}/>
</div>
);
}
}
class MyComponent extends React.Component {
someFunction() {
console.log('hello');
}
render() {
return(
<div>Hello World</div>
);
}
}
ReactDOM.render(<Parent/>, 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'/>
But i will suggest you to pass a function from parent component to child component and use that function to pass data or for any other purpose instead of using ref.
I'm a debutant with react, i read the doc. It's a general question.
I understand how to pass a props from a child component to a parent component. But, I don't understand how to pass a props from a parent component to the child component.
So in the picture, to pass a props from list to app, i do that :
in list component :
interface Props {
onCreateDoc : () => void
}
And in my app component :
I call list with the props :
<List onCreateDoc={this.onCreateDocCb}/>
And i implement the function :
onCreateDocCb = () =>{
// code of function
}
But I don't know how to pass a props from app to form. How can i do that ? Thank you
It's easier to understand how to pass props then how to receive props.
You add props to your Form Component that way:
const bar = "bar"
const fooBar = () => console.log("fooBar")
<Form stringProps="foo" varProps={bar} funcProps={fooBar}/>
Inside your Form Component you can acces it via this.props.stringProps.
Here you find examples: https://facebook.github.io/react/docs/components-and-props.html
Edit: Here is a snippet with a App and a Form Component and props passed from App to Form
// Example stateless functional component
const Form = ({ label }) => (
<div style={{color: "blue"}}>{label}</div>
);
// Example class component
class App extends React.Component {
render() {
const {title} = this.props;
return (
<div>
<div>{title}</div>
<Form label="label from props" />
</div>
);
}
}
// Render it
ReactDOM.render(
<App title="title from props" />,
document.getElementById("react")
);
<div id="react"></div>
<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>
I'm working on a project that uses react-typeahead and attempting to implement a custom component for the dropdown list. React-typeahead accepts a customListComponent prop.
However, I need to pass a prop to the component that is being passed into the Typeahead component. Initially, I tried setting a variable as a the custom component:
//MainSearch.js
import SearchOrderComponent from './SearchOrderComponent'
export default class MainSearch extends React.Component {
//Constructor here
render() {
let customList = <SearchOrderComponent ranking={this.state.ranking} />
return(
<div className="search-container">
<Typeahead customListComponent={customList} />
</div>
)
}
}
This caused an invariant violation, with react stating that a react component was expected. My current workaround is to make SearchOrderComponent a function that accepts the paren't state as an input and returns a react component, like so:
//SearchOrderComponent.js
const wrapper = function(ranking){
let SearchOrder = React.createClass({
render: function() {
var searchRanking = ranking.map(function(item){
return <li key={item.key}>{item.value.niceName}</li>
});
return(
<div className='main-dropdown'>
{searchRanking}
</div>
);
}
});
return SearchOrder;
}
module.exports = wrapper;
Now I can input this function directly into the typeahead component:
//MainSearch.js
<Typeahead customListComponent={SearchOrderComponent(this.state.ranking)} />
But this feels like a break from the component API. Is there a more direct/proper way to do this?
If I understand correctly what you're trying to achieve, the most direct way would be
render() {
return(
<div className="search-container">
<Typeahead>
<SearchOrderComponent ranking={this.state.ranking} />
</Typeahead>
</div>
)
}
You can access the SearchOrderComponent from within the Typeahead component via this.props.children.