205

I've upgraded from React Native 0.54 to 0.57 and my application has fallen over, due to using React Native elements.

I used the error functionality of TextInput components, which enabled props that can set and style the error message.
Very convenient, but the upgrade has broken these, and I'm now greeted with this error:

Invariant Violation: Text strings must be rendered within a <Text> Component.

Invariant Violation: Text strings must be rendered within a  Component.

So I've deleted that code and the error disappears.
However, I'm still receiving the issue when I run this code:

{ this.state.event.cards[i].fields[j].error && 

  <Text style={{ color: '#e74c3c', fontSize: 14, paddingLeft: 5 }}>
    {this.state.event.cards[i].fields[j].error}
  </Text>
}

When I begin typing in the text-input, it sets the error message to an empty string.
So if an error is returned, typing in the field will make the error go away.

My goal is to check if this.state.event.cards[i].fields[j].error is a non-empty string, and if so, display it.

3
  • I got this from just returning text inside <p></p>, as I wanted to create components that worked with regular React and React Native. Changing it to <></> worked, but it's annoying that the components are harder to share between the two paradigms. Commented Oct 17, 2022 at 10:24
  • It is very important to note that debugger stack trace sometimes might not point to the exact line of the occurrence. In my case it was pointing to a setState's setCart function while the string printed without <Text> tag was in the view part. It took me more than an hour to figure this out. Ref. dropbox.com/scl/fi/4tho94eek4ho1girnv8u9/… & dropbox.com/scl/fi/jsfjk91bpajcog5trz9q0/… Commented Dec 18, 2023 at 4:40
  • Please also check if you have accidentally pressed any key from Keyboard, which will also trigger this error Commented Jul 22, 2024 at 16:38

54 Answers 54

456

I've shot myself in the foot too many times over this, so I'm leaving this here for the next person not to...

Whenever you see

Invariant Violation: Text strings must be rendered within a <Text> component

99% of cases will be caused by using conditional rendering with only && instead of ternary ? : statements. Why? Because when your condition resolves to undefined, there are no components there, as opposed to null or an empty array which would have safely showed an empty space and save your life from the red screen of hell.

Change ALL OF YOUR LOGICAL CONDITIONAL RENDERS into ternary renditions.

ie:

DON'T DO

widgetNumber === 10 && <MyComponent />

DO DO

widgetNumber === 10 ? <MyComponent /> : null

Every Single Time. Please. For the love of react native.

Sign up to request clarification or add additional context in comments.

13 Comments

@NickTiberi it works because when you return an empty object it is not a valid component to return to render, however empty array is. When you have a conditional block, and condition is false, and you don't have a fallback component or array returned, invariant violation happens due to an invalid component being returned. Hope this helps.
Returning null instead of an empty array also works and is perhaps a better fit semantically.
Another thing you can do instead of the ternary above is convert your expression to something like Boolean(myString) && <MyJSX/>
I started my studies now in react and I was managing to solve this error by always reloading the application but I didn't understand why this happened. Now that I know I will never go through the long, boring process of recharging all the time. Thank you very much.
Expo's ImagePicker example has the same mistake and can take forever for beginners to pick that error up. Thank you so much for saving time.
|
133

This also occurs when you have /* Comments */ in your return() function.

3 Comments

Thank you, removing the comments from the view worked for me
I do want to put comments in the return() block though so I figured out that I only get error if the comment is in the same line with components code. After I moved my comment to its own line the error goes away even though it is still in the return() block.
You can still use comments, just put them in brackets as well: {/* comment */} should do the trick anywhere.
83

For me the following code works fine, as long as this.state.error === undefined or it is not an empty string.

render() {
  return (
    <View>
      {this.state.error &&

        <Text>
          Error message: {this.state.error}
        </Text>
      }
    </View>
  );
}

If the error state is changed to empty string '', you will have the aforementioned exception: Invariant Violation: Text strings must be rendered within a <Text> component

The reason of that is, when this.state.error === '', the following expression will be evaluated as empty string, i.e., '', and this will cause Invariant Violation: Text strings must be rendered within a <Text> component

{this.state.error &&

  <Text>
    Error message: {this.state.error}
  </Text>
}

When this.state.error === undefined, the expression will be evaluated as undefined, which is what we expect, and it's fine.

2 Comments

This is a really great explanation, thank you for this. I’m happy to mark this as correct.
you can also write it like this: {Object.keys(this.state.error).length>0 && <Text> Error message: {this.state.error} </Text> }
65

I'd use !! which I call bang bang operator to boolianize error. That should work.


{!!this.state.error && (
  <Text>
    Error message: {this.state.error}
  </Text>
)}

If error is a string(even empty string), it must be wrapped with <Text /> in React Native, which is different from web.

5 Comments

On react 59.9, this fixed the error for me. Turns out the value was an empty string. Oddly enough, the error only happened in Android.
Seemed wacky at first, but it worked! I'm sure the person reviewing my code is gonna have questions though... More elegant then using ternary renditions imo.
Your answer deserves an upvote because of the name you gave to the operator
I had a similar issue with BE passing False in variable after sometime they started passing 0, which seemed to cause an issue, while both are same.
Damn this worked like a charm for me
29

In my case, it was a semicolon at the end of JSX syntax.

// wrong:
<View>
  <MyComponent>;
</View>

// correct:
<View>
  <MyComponent>
</View>

6 Comments

This was the case for me as well. You could wrap the components in parenthesis as well like return (<View/>);
ohh my GOD. You saved my life. I would never discover this alone.
ESLint kept doing this to me on autosave. I had to set semi to ["error", "never"].
Yea I had a semicolon next to my stack component in my _layout.tsx
had a semicolon at the end of a conditional render causing this similarly. such as {boolean ? (<> </>) : null};
|
22

This occurs when you use a string or numeric values in && operators.

For example:

const [a, setA] = useState('')
const [b, setB] = useState(0)

Here, both a && <View /> and b && <View /> will throw this error.

You need to have this conditional value as an true/false, null, or undefined data type.

Instead of using the string and numeric data types straight forward, you should convert them to Boolean type.

Correct implementation should be:

!!a && <View /> and !!b && <View />

or

for negation; !a && <View /> and !b && <View />

Comments

16

Delete space between components outside

<Text></Text>

Ex. Don't use

<Button> <Text>hi</Text></Button> 

But use

<Button><Text>hi</Text></Button>

2 Comments

This worked for me.
Thank you. For months I hated this problem. Now, I know to be careful about three things for this error. 1- Unnecessary spaces as you mentioned 2- ternary operation failure 3- Using one tag with />
13

In my case, this error occurred due to the presence of semi-colon ';' at the end of the closing of Text tag. For all those who don't get the appropriate answer above, try this. By removing semi-colon, the error disappeared.

Image of the Error code

As mentioned in the above image I also encountered this error due to the semi-colon ';'

Comments

9

For me, it happened because of an unopened curly brace inside JSX.

<View>
        {events.map(event => {
          return (
            <Card title={event.summary}>
              <Text>Date: {event.start.dateTime}</Text>
            </Card>
          );
        })}
        } <------------ that was the culprit
</View>

1 Comment

Something similar for me, but with a ).
9

Had the same problem and @serdasenay comment made me realize the root cause.

Using the syntax {condition && <Element/>} is not wrong per se, but it's important to know whats going on.

The root of the problem is logic short-circuiting. In Javascript logic expressions evaluates, and && evaluates to the last true equivalent value. But not to true, but to the actual value before it's cast to boolean. That's what acctually allow this syntax to begin with. Since <Element/> is always true if condition is true, the expression evaluates to <Element/>

The problem arises when the condition is false. When a && expression fails, it evaluates to the first value i.e condition. But before it being cast to boolean. So, if you use a direct string or number as condition and it evaluates to false the logic expression will evaluate to that string or number. Ex.: {array.length && <List/>} with a empty array evaluates to {0} which throws the error.

The solution is to make sure condition is a real boolean value (and that works because React can deal with rendering booleans - it think React just ignores them). So do the following: {array.length > 0 && <List/>}

1 Comment

Thanks! It turned to be the case with me too.
6

This usually happens when you do inline conditional rendering. You should delete white space between Text and your condition like below.

{ this.state.event.cards[i].fields[j].error && <Text style={{ color: '#e74c3c', fontSize: 14, paddingLeft: 5 }}>
    {this.state.event.cards[i].fields[j].error}
  </Text>
}

5 Comments

I have it all written on one line, with no whitespace as I read whitespace could cause this issue. After changing it to your answer I was still greeted with the answer, unfortunately in this case it did not work. //edit: I spaced it out on here so it could be read better, apologies for the confusion.
I've put it on a gist for you.
I didn't notice anything wrong. What's your error field value?
error is undefined until an error occurs or you begin typing in that field, once you type in that field it becomes a string. I have managed to solve this issue by changing this.state.event.cards[i].fields[j].error to typeof this.state.event.cards[i].fields[j].error === 'string' && this.blah.blah.length > 0 && <Text>stuff here</Text>
Sometime due to semicolon also its throw error. In my case i am having semicolon its throwing same. I removed it got solve.
6

For me it was the wrong import with IntelliSense. It imported the Button from'react-native-web' instead of 'react-native'. Once you run on the phone you get the this error.

Comments

6

In my case, it was a random letter after the self-closing component like this

<Card />r

Comments

5

From reading other answers here, this error message is vague and is shown for various reasons. I've gotten it when writing comments or even small white-space within views (crazy yeah...)

for example: <View> {props.children} </View>

must be changed to: <View>{props.children}</View>

1 Comment

Omg...I'm so tired of this vague error with all these random solutions. Last time it was because of /* */ comments. This time it's because I have a SPACE before {props.children}...The first few times I received the error, who KNOWS what the solution was...
5

i'm an absolute beginner to react native and my mistake was importing Text, Flatlist from react-native-web instead of just react-native, it's automatically happens on vs code and i don't know why!

DON'T

import { Text, FlatList, StyleSheet } from "react-native-web";

DO

import { Text, FlatList, StyleSheet } from "react-native";

Comments

4

In my case it occurred because comments in render function

// Some comment here

Solutions:

  • Remove the comment
  • or make it like this {/* Same comment here*/}

1 Comment

I have this error and in my case it was solved by also removing the commenting option I used // I removed it in some cases and in others I replaced it with {/* */} and it started working again
4

Sometimes Prettier or your code formatter will add this to your JSX when you save.

<View>
{' '}
</View>

Remove this and you should be fine.

2 Comments

This works for me.
Thanks for this solution, I struggled a lot to get the error.
4

As for me I had this error because of a trailing ';' I changed :

<Divider orientation="horizontal" />;

To :

<Divider orientation="horizontal" />

Comments

3

In my case, I had to remove space between View tag and Text tag from

<View>  <Text style={{ color: "white"}}>Start</Text> </View>

to

<View><Text style={{ color: "white"}}>Start</Text></View>

1 Comment

I head my head many times. Even it helps me to clear the error
3

If there is any space between your and (in same line) then also this error can come.

**eg: <Text> <Button>click me<Button><Text>**

           ^(make sure that you have no space if it is in same line)



  

make sure to avoid space between two tags if it is in same line.

Comments

3

Solution

!! will resolve this issue.

{!!error && <Text>{error}</Text>}

Explanation

  • if we use single not ! operate and assign empty "" string then !"" will become true and will render empty string because we are converting string to boolean !"" => true

Comments

3

I had the same issue and the mistake was space(s) between the opening/closing tag of the element and its child/content, such as <Provider> {children} </Provider>.

Note: Remove any space close to {children}.

Correct:
<Provider value={something}>{children}</BlogContext.Provider>
Wrong:
<Provider value={something}>{children} </BlogContext.Provider>
//                                   ^^^ - space that causes the error
Also wrong:
<Provider value={something}> {children}</BlogContext.Provider>
//                         ^^^ - space that causes the error

Comments

2

I encountered the same error message in VSCode yet I didn't have /* Comments */ or any expressions. The solution was to remove the formatting in something like textedit or word and copy+paste the code back to vscode.

I do not know why or how it works (perhaps it specifically happens in VSCode), but the formatting issue is something I also have experienced with SDL in graphql...

Comments

2

For me it was because I added a comment after another component.

enter image description here

Thankfully, Git helped me with the trial and error process.

2 Comments

Yeah I had this too. So dumb. Comments are literally meant to be ignored
2

None of the answers were working for me as I searched my code up and down and couldn't find a typo or extra spacing as I use prettier, so checked it's settings as well.

The error for me was occurring because I was rendering a UI like this:

distance && (<Text>...

When the value of distance is 0 that is what was causing this error for me. Changing it to distance !=== undefined fixed it.

Hope this helps someone someday as it took me a while to find this culprit.

Comments

2

When I format the code it's putting ; after the ; which causing the error. Before:

export default () => {
  return (
    <BlogProvider>
      <App />;
    </BlogProvider>
  );
};

Now if you remove the ; the error while resolve. So, make sure your formatter does not add ; at the end of line automatically. After:

export default () => {
  return (
    <BlogProvider>
      <App />
    </BlogProvider>
  );

Comments

1
{this.state.password.length > 0 && <Text>}

This will throw the same error, because it returns undefined. We can render it like this -

{this.state.password.length > ? <Text> : null}

Comments

1

Use this code given below if the initial value is an empty string. Or conditionaly check with the initial value. Here I conditionaly check when the error is not empty then show the error.

{this.state.error !== '' && (
    <Text>
      {this.state.error}
    </Text>
)}

Comments

1

For me it was due to the misplacement of closing > in TouchableOpacity React native touchable Opacity.

Faulty code :

<TouchableOpacity>
        onPress={() => this.setState({ showOverLay: true })}
          <Image
            source={cardImage}
            resizeMode="contain"
            style={[
              styles.cardImage, cardImageStyle
            ]}
          />
</TouchableOpacity>

Good code :

  <TouchableOpacity
        onPress={() => this.setState({ showOverLay: true })}>
          <Image
            source={cardImage}
            resizeMode="contain"
            style={[
              styles.cardImage, cardImageStyle
            ]}
          />
</TouchableOpacity>

Comments

1

Conditions with '' (empty string) not working. Change them to null

Not Working:

<ButtonBorderLarge
    buttonText={'Choose certificate'}
    onPressHandler={pickCertificate}
    icon={docName ? 'check' : ''}
/>

Working:

<ButtonBorderLarge
    buttonText={'Choose certificate'}
    onPressHandler={pickCertificate}
    icon={docName ? 'check' : null}
/>

Comments