In my AutoSuggest Component (which renders FlatList), I would like to render different types of cells.
I'd like to pass different Components into AutoSuggest, such as:
<Suggest
customCell={<SimpleUserCell/>} //or any type of cell
/>
Inside Suggest.js, my render will look like this:
render(){
<FlatList
renderItem={(props) => {
return(
<this.props.customCell extraData={this.suggestData}/>
)
}}
/>
}
How can I achieve this?
To pass a component as a prop in React Native you can do the following, can be seen at: https://codesandbox.io/s/6v24n3q92z Hopefully this helps. You will need to extrapolate to get your specific use case working.
class ComponentOne extends React.Component {
render() {
return (
<div>
I am Component One see my array
<ul>{this.props.extraData.map(number => <li>number {number}</li>)}</ul>
</div>
);
}
}
class Suggest extends React.Component {
render() {
var anArray = [1, 2, 3, 4, 5];
var CustomComponent = this.props.customCell;
return <CustomComponent extraData={anArray} />;
}
}
function App() {
return <Suggest customCell={ComponentOne} />;
}
Related
I'm using the following template: https://github.com/cawfree/create-react-native-dapp
I have used the provider component in the top level (parent) component like so:
import { Provider } from 'mobx-react';
import SettingsStore from '../../store/settings';
return (
<Provider store={SettingsStore}>
<View style={[StyleSheet.absoluteFill, styles.center, styles.white, !loading && {justifyContent: 'space-between'}]}>
{loading ?
<FadeOutImage />
:
<Welcome />
}
</View>
</Provider>
);
Here's my SettingsStore in file settings.js:
import {makeAutoObservable} from 'mobx';
class SettingsStore {
darkMode = false
constructor() {
makeAutoObservable(this)
}
toggleDarkMode = () => {
this.darkMode = !this.darkMode
}
}
export default new SettingsStore();
The following is where I am injecting the store. It's the child component <Welcome />:
import { inject, observer } from "mobx-react";
const Welcome () => {
return (<View><Text>test</Text></View>)
}
export default inject("SettingsStore")(observer(Welcome));
I have checked that the paths for the imports is correct (would get another error otherwise). I just cannot understand why I am seeing the following err:
What's going wrong and how can I fix this?
You passing in under the name store into Provider (<Provider store={SettingsStore}>), so when injecting you need to use same prop name inject("store"). Or change prop name to SettingsStore: <Provider SettingsStore={SettingsStore}>
I am using React 16.8.6 and I have the following structure:
page.js
<ParentComponent id="testData">
<ChildComponent value={data => data.text} />
</ParentComponent>
parentComponent.tsx
export default class ParentComponent extends React.PureComponent<IParentProps> {
...
render() {
const items = this.props.children;
<MiddleComponent items={items} />
}
}
ParentContainer.ts
import { withTranslation } from 'react-i18next';
import ParentComponent from './ParentComponent';
export default withTranslation()(ParentComponent);
I need to know inside of MiddleComponent the element type (not as a String but as a React element since I am going to create a new Element based on it) of each child (so, in this case I should have ChildComponent), but when I inspect with chrome, all my children have a I18nextWithTranslation type...
Any idea how to fix this? Or if this is maybe a known bug?
If I don't use any hoc at all, when I write child.type it returns me ChildComponent(props). But this is not true to when I am using hocs to wrap the parent...
The issue was very stupid...
I was importing the <ChildComponent> as a default import even though the child was not exported as default.
Basically
import ChildComponent from '' instead of import { ChildComponent } from ''
In the example below, we're setting Component.displayName on our components so we can access that property in parents. This is a super trivial example that could be expanded to work with an array of children if needed.
const ChildComponent = () => {
return <div>child render</div>
}
ChildComponent.displayName = "MyComponentName"
const ParentComponent = ({ children }) => {
// This is the type of component.. should output "MyComponentName"
const childType = children.type.displayName
return (
<div>
<h1>Render Children</h1>
{children}
</div>
)
}
function App() {
return (
<ParentComponent>
<ChildComponent />
</ParentComponent>
)
}
Can I use a child components state in App.js? I mean, in a child component I have a variable for example i = 5 and I would like to use this in App.js. In App.js this.state.i shows 0.
This is a very basic pattern in react so maybe just read through the official docs oder do some tutorials for getting started with react.
But to help you out on this you need to pass down a function to your child that sets the state in <App/>
So something like this:
App:
this.state { i : 0 }
updateState() {
this.setState(i: i + 1); // or whatever
}
render() {
return (
<>
<Child updateState={this.updateState} />
</>
....
Child:
<div onClick={props.updateState}>Click me</div>
On app.js do this;
constructor(props) {
this.updateI=this.updateI.bind(this)
super(props)
this.state = {
i:0
}
}
updateI(i){
this.setState({i})
}
render() {
return (
<View >
<Child updateI={this.updateI}/>
</View>
)
}
on your child do this:
this.props.updateI(5);
I am following this question's first answer to create a common parent for two of my components
import React, {Component} from 'react';
import ButtonSubmit from './ButtonSubmit'
import Form from './Form'
export default class ParentofButtonandForm extends Component {
constructor() {
super();
this.state = {
username: '',
password : '',
};
}
changeFirst(receivedUN,reaceivedPW) {
this.setState({
username: receivedUN,
password:reaceivedPW
});
}
render() {
return (
<Form username={this.state.username} password={this.state.password} changeFirst={this.changeFirst.bind(this)}/>
<ButtonSubmit username={this.state.username} password={this.state.password}/>
)
}
}
But i get unrechable code error in
<ButtonSubmit username={this.state.username} password={this.state.password}/>
I dont know what i am doing wrong. I also get a ':expected' warning in this.state.username.
You are returning two components from render functions. Either you wrap <Form> and <Button> into another component, may be View OR you can return a component array from render function.
Wrapping inside View
render() {
return (
<View>
<Form .../>
<ButtonSubmit .../>
</View>
)
}
Returning array of components, link
render() {
return [
<Form .../>,
<ButtonSubmit .../>
];
}
Hope this will help!
Assuming the following and all the components/fus/fci/ssg have just a single h1 with a site props. I want to understand why it is a valid react element yet these are not showing equally rendered. That is one has the h1 element and the other doesn't. The idea was to not create large component with toggles for different sites and each site would be swapped out based on the nav pick. I don't see anything documented for this unless I missed it...
{this.state.renderSite}
<Fci site="Fci"/>
import React from 'react';
import styles from './App.css';
import Nav from '../components/Nav.js'
import Fus from '../components/Fus.js'
import Fci from '../components/Fci.js'
import Ssg from '../components/Ssg.js'
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {renderSite: '', site: 'default' };
this.pickSite = this.pickSite.bind(this);
}
pickSite(site){
this.setState({renderSite: React.createElement(site, {"site":site})});
this.setState({site: site});
console.log( React.isValidElement(this.state.renderSite));
}
render() {
return (
<div className={styles.app}>
<Nav site={this.pickSite.bind(this)} />
{this.state.renderSite}
<Fci site="Fci"/>
</div>
);
}
}
The Nav
import React from 'react';
export default class Nav extends React.Component {
constructor(props) {
super(props);
this.update = this.update.bind(this);
}
update(e) {
this.props.site(e.target.dataset.site);
}
render(){
return (
<div>
<button onClick={this.update} data-site="Ssg"> SSG </button>
<button onClick={this.update} data-site="Fci"> FCI </button>
<button onClick={this.update} data-site="Fus"> FUS </button>
</div>
);
}
}
The problem is when you create the element you are passing a string (data-site value), not a component reference. So it ends up like this:
React.createElement("Fci");
As opposed to:
React.createElement(Fci);
Using a string will create a simple HTML element, not a component with with its own rendered content.
You could create a component map like this:
const componentMap = {
"Fci": Fci,
"Fus": Fus,
"Ssg": Ssg
}
Then from your string you can resolve a component reference:
React.createElement(componentMap[site], {site: site});
Or you could pass a component reference from your Nav:
<button onClick={this.update.bind(this, Ssg, "Ssg"}> SSG </button>
update(component, site, e) {
this.props.site(component, site);
}
pickSite(component, site) {
React.createElement(component, {site: site});
}