Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Context: TypeError: render is not a function

Tags:

I'm trying to use React Context to pass a function to a nested child component, which effectively allows the child to update the parents state when pressed.

The problem is I seem to be getting an error 'TypeError: render is not a function. (In render(newValue), render is an instance of Array' and an error in my console reads: 'Warning: A context consumer was rendered with multiple children, or a child that isn't a function. A context consumer expects a single child that is a function. If you did pass a function, make sure there is no trailing or leading whitespace around it.'

I've looked around at this error and also at documentation but no answers seem to answer my question, I can't quite work out why this isn't working.

EDIT: I should add that there are multiple child components rendered, as they're built from an array of objects

Snippets:

Parent:

class Product extends Component {     state = {         selected_ind: 0     };      handleContextChange = selected_ind => {         this.setState({selected_ind});     };      render() {         const contextValue = {             data: this.state,             handleChange: this.handleContextChange         };          //Desconstruct props for ease of use         const {             attr_data,             variant,             product_name } = this.props;           return (                 <Container>                     <Heading>Product Options</Heading>                     <IndexContext.Provider value={contextValue}>                         <OptionTile                             tileColor='grey'                             onPress={ () => this.props.navigation.navigate('Variants', {                                 attr_data: attr_data,                                 selected_ind: this.state.selected_ind                             })} //Replace with named function                             option="Variant"                             selected_ind={ this.state.selected_ind }                             value={ selected_attr.name } />                     </IndexContext.Provider>                     <OptionTile                         tileColor='grey'                         option="Quantity"                         value="1" />                 </Container> 

Within OptionTile is the child I'd like to use the function within:

const VariantTile = (props) => {     return (         <IndexContext.Consumer>             {({ handleChange }) => (                 <TouchableOpacity onPress={handleChange(props.index)}>                     <AsyncImage                         source={ props.img_src }                         placeholderColor="#fafafa"                         style={{ flex: 1, width: null, height: 200 }}                     />                     <Text>{ props.var_name }</Text>                     <Text>{ props.price }</Text>                     <Text>{ props.sku }</Text>                 </TouchableOpacity>             )};         </IndexContext.Consumer>     ) }; 

And the context component is simple:

const IndexContext = React.createContext();  export default IndexContext; 
like image 237
Adam Roberts Avatar asked Jan 22 '19 09:01

Adam Roberts


People also ask

Do all React Native components need to be compatible with enzyme?

They all have to match. Separately, there doesn't yet exist a react native adapter for enzyme (see #1436 ), so until there is, enzyme won't work properly with many kinds of react-native components. @ljharb I have updated enzyme & enzyme-adapter-react-16 and tried still getting same error,

Why test is not running after updating React-Native and jest dependencies?

After updating all the react-native and jest dependencies for app, test is not running its throwing error like this, Try updating to the latest enzyme and enzyme-adapter-react-16; also, what version of react and react-dom and react-test-renderer are you using? They all have to match.

What is a context consumer in JavaScript?

A context consumer was rendered with multiple children, or a child that isn’t a function. A context consumer expects a single child that is a function. If you did pass a function, make sure there is no trailing or leading whitespace around it.


1 Answers

As the error states, <Consumer> should have the only child, and it should be a function. The error appears when it has multiple children, including text nodes.

; after embedded expression causes the problem. It's not a part of an expression, and making it a part of it would result in syntax error.

It should be:

<IndexContext.Consumer>     {({ handleChange }) => (         <TouchableOpacity onPress={handleChange(props.index)}>             <AsyncImage                 source={ props.img_src }                 placeholderColor="#fafafa"                 style={{ flex: 1, width: null, height: 200 }}             />             <Text>{ props.var_name }</Text>             <Text>{ props.price }</Text>             <Text>{ props.sku }</Text>         </TouchableOpacity>     )} </IndexContext.Consumer> 
like image 73
Estus Flask Avatar answered Sep 20 '22 23:09

Estus Flask