175

I've upgraded from RN 0.54 to 0.57 and my app has pretty much fallen over due to using React Native Elements.

I took use of their error functionality on TextInput components which basically enabled props that you could style the error message and set your error message. Very convenient, however the upgrade has broke these and I'm now greeted with this error:

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

So I've delete 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 to type in to a text input, it sets my error message to an empty string, so if an error is returned typing in the field will make the error go away.

As soon as this.state.event.cards[i].fields[j].error becomes a string, I get returned this error. However you can see I check to see if error exists, then I just display the error, or try to at least.

Another set of eyes would be grateful on this one.

  • Make sure your JSX is error free and you didn't accidentally added any unexpected text. – Shiva Jun 08 '21 at 01:44
  • I got this from just returning text inside `

    `, 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.
    – Rob Grant Oct 17 '22 at 10:24

50 Answers50

351

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.

sed
  • 5,431
  • 2
  • 24
  • 23
  • 3
    @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. – sed Oct 01 '20 at 03:01
  • 2
    Returning null instead of an empty array also works and is perhaps a better fit semantically. – ToneCrate Dec 08 '20 at 08:52
  • 2
    Another thing you can do instead of the ternary above is convert your expression to something like Boolean(myString) && – Shane Sepac Mar 24 '21 at 19:40
  • 1
    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. – Vinicius Vasconcelos Jul 04 '21 at 05:33
  • 1
    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. – Saurabh Oct 16 '21 at 06:10
  • 1
    Had this in our codebase! Now using https://github.com/hpersson/eslint-plugin-jsx-expressions as to prevent this bug in the future – Jef Vandooren Jan 17 '22 at 12:11
  • 1
    This answer is not true anymore and React have fixed this – arled May 20 '22 at 21:55
  • I believe `&&` should still work as long as the `&&` logic (and component) are wrapped in a fragment, i.e. <><>... though I haven't tested this – fullStackChris Jul 13 '22 at 12:02
96

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

starball
  • 20,030
  • 7
  • 43
  • 238
Tare Gaskin
  • 1,209
  • 2
  • 10
  • 13
76

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.

Yuci
  • 27,235
  • 10
  • 114
  • 113
  • 2
    This is a really great explanation, thank you for this. I’m happy to mark this as correct. –  Jan 27 '19 at 00:08
  • you can also write it like this: {Object.keys(this.state.error).length>0 && Error message: {this.state.error} } – MING WU Sep 02 '19 at 01:00
56

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.

Otani Shuzo
  • 1,118
  • 1
  • 11
  • 22
  • 4
    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. – twelve17 Aug 17 '19 at 11:54
  • 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. – Themis Feb 18 '22 at 09:43
  • Your answer deserves an upvote because of the name you gave to the operator – Yuniac Jul 21 '22 at 10:49
  • 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. – Sami Ullah Jan 31 '23 at 10:41
17

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 />

starball
  • 20,030
  • 7
  • 43
  • 238
Manish
  • 471
  • 1
  • 10
  • 22
10

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 ';'

Sarthak Sharma
  • 105
  • 1
  • 4
10

Delete space between components outside

<Text></Text>

Ex. Don't use

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

But use

<Button><Text>hi</Text></Button>
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
Tanveer Rifu
  • 147
  • 1
  • 6
  • This worked for me. – Zain763 Sep 22 '21 at 17:13
  • 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 /> – nogabemist Dec 07 '21 at 12:57
9

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

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

// correct:
<View>
  <MyComponent>
</View>
exoslav
  • 2,094
  • 3
  • 21
  • 26
8

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>
Ben Butterworth
  • 22,056
  • 10
  • 114
  • 167
8

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/>}

Lucas Falcão
  • 81
  • 1
  • 2
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.

mrdzawesove
  • 91
  • 1
  • 4
5

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>
}
Melih Mucuk
  • 6,988
  • 6
  • 37
  • 56
  • 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. –  Sep 17 '18 at 13:18
  • I've put it on a [gist](https://gist.github.com/mikerodham/fba1fb6651a4c01bed93a86c8e2a7725) for you. –  Sep 17 '18 at 13:21
  • I didn't notice anything wrong. What's your `error` field value? – Melih Mucuk Sep 17 '18 at 13:33
  • `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 && stuff here` –  Sep 17 '18 at 13:43
  • Sometime due to semicolon also its throw error. In my case i am having semicolon its throwing same. I removed it got solve. – Avinash Dalvi Oct 11 '19 at 09:48
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>

SilverTech
  • 399
  • 4
  • 11
  • 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... – velkoon Jul 11 '22 at 17:04
5

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

<Card />r
Kristina
  • 101
  • 1
  • 5
4

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

<Divider orientation="horizontal" />;

To :

<Divider orientation="horizontal" />
victordax
  • 41
  • 3
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>
Abdes
  • 926
  • 1
  • 15
  • 27
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.

starball
  • 20,030
  • 7
  • 43
  • 238
3

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";
Nivethan
  • 2,339
  • 19
  • 22
2

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

<View>
{' '}
</View>

Remove this and you should be fine.

Richard Torcato
  • 2,504
  • 25
  • 26
1

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...

hksande
  • 11
  • 1
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}
U13-Forward
  • 69,221
  • 14
  • 89
  • 114
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>
)}
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>
Deepak
  • 2,287
  • 1
  • 23
  • 30
1

For me, the error was because I initialized the state object as an empty string.

const [category, setCategory] = useState("")

If the state is going to be an object, then it must be set to null in the beginning.

const [category, setCategory] = useState(null)
starball
  • 20,030
  • 7
  • 43
  • 238
za_ali33
  • 366
  • 2
  • 9
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}
/>
Arosha
  • 1,311
  • 2
  • 16
  • 22
1

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
Muhammad Numan
  • 23,222
  • 6
  • 63
  • 80
0
 <React.Fragment>
      {this.props.title ? (
        <React.Fragment> 
          <Text>  true </Text>
        </React.Fragment>
        ):(             
           <React.Fragment> 
          <Text>  false </Text>
          <Text>  false </Text>
        </React.Fragment>

You have to wrap with View tag or React.Fragment tag and inside you need also wrap if element more then one

Naved Khan
  • 1,699
  • 16
  • 13
0

try this :

<>
    <View>
    {this.state.error &&
      <Text>
        Error message: {this.state.error}
    </Text>
   </View>
</>
Emad Deym
  • 11
  • 2
0
In my case some part of the code was out side the text component for example:
<RadioForm style={styles.radiobutton} 
                      radio_props={hobbies}
                      initial={1}
                      onPress={(value) => {ToastAndroid.show(value.toString(), ToastAndroid.SHORT)}}
                      buttonSize={4.5}
                      buttonOuterSize={19}
                      selectedButtonColor={'green'}
                      selectedLabelColor={'green'}
                      labelStyle={{ fontSize: 14, }}
                      disabled={false}
                      formHorizontal={true}
             />
<RadioForm

this above line < RadioForm is left unclosed that is the reason

Teju
  • 41
  • 4
0

I had the same issue and the mistake was adding space between the children and the component such as {children}

Note: Remove any space close to {children}

 <Provider value={something}>{children}</BlogContext.Provider>
DiaMaBo
  • 1,879
  • 1
  • 18
  • 18
0

This occurred for me because I was using a lower-case function name by accident:

export const p = (props) => {
  return (
    <Text style={[styles.p]}>{props.children}</Text>
  );
};

Should be:

export const P = (props) => {
  return (
    <Text style={[styles.p]}>{props.children}</Text>
  );
};

Notice in the second one the p is capitalized. This is needed in order for the components to be detected as React Native components.

Eric Wiener
  • 4,929
  • 4
  • 31
  • 40
0

I had the same problem, In my case I had an <AppText> component which shows simple formatted <Text> under the hood.

First code was like

<AppText> </AppText>

while I was trying different things I just wrote it with self-closing syntax

<AppText />

then problem was suddenly solved.

I think it was just about a special & invisible character I wrote between tags by mistake or this character was coming from VSCode by auto-complete feature or snippets, because I couldn't repeat the error by placing a space.

Bulent Balci
  • 644
  • 5
  • 11
0

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*/}
ATQSHL
  • 381
  • 3
  • 12
0

There is an operator !! which converts a string type to boolean and makes it false when variable is an empty string:

{!!error &&
  <Text>
    Error message: {error}
</Text>}
karan bhatia
  • 434
  • 1
  • 6
  • 20
0

This below code also check empty string and truthy value.

  return(
    <View>
    {!!this.state.error && <Text>{this.state.errorMessage}</Text>}
    </View>
  );
Sanjib Debnath
  • 3,556
  • 2
  • 22
  • 16
0

remove mark () from outside any components, this is use in after return and if statement in JSX ()

This is wrong: <View>(<Button/>)</View> This is true: <View><Button/></View>

Ahmad Tech
  • 21
  • 1
  • 1
0

In my case, I was naming the state text like the name of the component to make sure it s a different name.

Noor Ha
  • 1
  • 2
0

In my case Tanveer Rifu's answer worked. But in addition to that if you have spaces in your return statement, you can fix this by wrapping it in parenthesis () and using one line per each tag.

Example, instead of

const HelloWorld = () => {
    let counter = 0;
    return <View> <Button title="Increment"> </Button><Text>{ counter}</Text> </View>
} 

You can wrap it as below

const HelloWorld = () => {
    let counter = 0;
    return (
        <View>
            <Button title="Increment"></Button>
            <Text>{counter} </Text> 
        </View>
    )
}

But still if you're going to have more than one elemenent in single line do not leave spaces between the different tags.

v1shva
  • 1,261
  • 3
  • 13
  • 28
0

It is giving error on <Pressable> too. So avoid pressable instead of react native buttons. It may helpful to the people who are using react-native 6 or above.

Or else try this way

<Pressable titleSize={20} style={styles.button}>
  <Text>Pressable tab
</Text>
</Pressable>
  
Abishethvarman V
  • 129
  • 1
  • 1
  • 9
0

In my case I was importing

import { Button, View } from 'react-native-web';

instead of

import { Button, View } from 'react-native';

Make sure you are importing from correct package.

starball
  • 20,030
  • 7
  • 43
  • 238
napster
  • 687
  • 1
  • 8
  • 18
0

The error occurs when you the text node inside start or ends with space, for example <Text> I am here <Text>. Try to remove the space, i.e. <Text>I am here<Text>. In Touchable Opacity always use Text component to write a non-whitespace string and don't start or end it with space.

brennanyoung
  • 6,243
  • 3
  • 26
  • 44
0

It may also happen when you are importing something from react-native-web and using it in react-native and vice versa. If you are getting this error in react-native just search in all the imports and remove the web i.e (use import {Something} from 'react-native';)

Muhammad Iqbal
  • 109
  • 1
  • 9
0

Make sure you have the correct presets in babel.config.js:

module.exports = {
  presets: ['module:metro-react-native-babel-preset'],
  ...
}

I have a Next Js/React Native Web app embedded within my React Native app and toggle between the two. Toggling includes commenting out the 'module:metro-react-native-babel-preset' when running the Next Js app (in favor of using a Next Js preset). The result of running the React Native app without the 'metro' preset is the 'Text strings must be rendered within a <Text> component' error.

P. Avery
  • 779
  • 1
  • 16
  • 34
0

In my case I had made a mistake of using html h tags to define text instead of <Text/>

Zack
  • 472
  • 7
  • 16
0

I'm going to add an answer just to point out another possible way of getting this error like others have added here. As @abe kindly commented on my question here, I was using an unsupported tag (ul and li). It seems that these tags are supported by ReactJS but not by React Native, as Android/iOS don't have native support for <ul/> equivalent list. For more details please see my question here.

Sami
  • 11
  • 2
0

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.

0

In JSX, avoid returning empty string or undefined, it can cause app crash.

Instead return null.

Yuvraj Patil
  • 7,944
  • 5
  • 56
  • 56
-1
this.state.recording ?(<Text>{this.secondsToMMSS(this.state.seconds)}</Text>) :                                     (null)

text string must be rendered with in component

gehbiszumeis
  • 3,525
  • 4
  • 24
  • 41
-2

ok, so if you came this far down, its because you probably have the same issues as me for example:

return <View key={r}> {columns} </View>

and:

return <View style={styles.container}> {rows} </View>

you see there is a space beetween "> {" yeah, that's the whole issue, try deleting those.

codersl
  • 2,222
  • 4
  • 30
  • 33
Valn1
  • 109
  • 11
-5

Just remove the comments from the code, then it will work fine. I don't know any other alternative by the way! :)

  • 1
    Please consider reading other answers before providing your own, as this has already been mentioned by Tare Gaskin. –  Feb 24 '19 at 12:08