Error : Text strings must be rendered within a <Text> component - javascript

I am making an app that you can make shopping list, ans want to make a voice input but it gives me the error: Text strings must be rendered within a component
{this.state.results.map((text, index) => {
return (
<Text key={index}>
Mensagem: {this.state.results}
</Text>
);
})}```

Make sure you’re bringing your built in components from react-native, not react-native-web.
Import {View, Text, ...} from "react-native"

I'm not familiar with react-native, but it sounds like the Text component expects a string, but got something else. this.state.results sounds like an array, is that correct? If you're trying to render something for each result you'll need to do something like:
return (
<div>
{this.state.results.map(result => (
<Text key={index}>
Mensagem: {result}
</Text>
))}
</div>
);
If each object in the results array is an actual object and not a string, you'll need to use a property like {result.name} or whatever is appropriate.

There is nothing wrong with the code you posted.
The problem is instead a letter, number or other character hiding somewhere in your JSX. This typicly happens when you accidently press a button without noticing.
This wont show as a warning in your IDE (example Visual Studio Code).
You can try and narrow down where the problem is by commenting out diffrent sections of you code and if you dont get an error you know you have found what code snippet the bad character is hiding in.
I even inserted your code into a react native project of mine just to confirm it works.
{["H", "E", "L", "L", "O"].map((text, index) => {
return (
<Text key={index}>
Mensagem: {text}
</Text>
);
})}
For everyone that is not that familiar with react native error messages or Text components.
Text components have no problem handling arrays as long as you dont insert objects into them. When you pass an object into a react native Text component you get this error: "Objects are not valid as a React child".

Related

How can I put a prop for a function in a component in React Native

I'm in college and we are working with react native. For an assignment, I need to make an interface of a bookshop. I made a title, a shopping cart etc. and below, I've put a book title, the author, a description, ISBN, and a button that says 'read'.
I want to put all of this (per book) in a component, so I just need to use the component instead of duplicating my code. I know how this works and I use props and everything, but the book title and the button are clickable. Now, is there a possibility to put some kind of prop on the touchable so it knows which function it needs to run?
This is my component now:
const BookTile = (props) => {
return (
<View style={styles.bookoverview}>
<Text style={styles.bookauthor}>van {props.author}</Text>
<Text style={styles.description}>{props.description}</Text>
<Text style={styles.isbn}>ISBN {props.isbn}</Text>
</View>
);
}
export default BookTile;
And this is the part in my app file:
<TouchableWithoutFeedback onPress={() => title1()}><Text style={styles.booktitle}>Iene Miene Mutte</Text></TouchableWithoutFeedback>
<BookTile author="M.J. Arlidge" description="Het meisje was..." isbn="978-9-0225-7622-9"/>
<TouchableHighlight underlayColor="lightgrey" onPress={() => book1()} style={styles.tile}>
<View>
<Text style={styles.tileText}>GELEZEN</Text>
</View>
</TouchableHighlight>
So I put my button and my title separatly, so I can use this function when I press them:
function book1() {
console.log("Iene Miene Mutte - GELEZEN");
}
function title1() {
console.log("Iene Miene Mutte - TITEL GEKLIKT");
}
I hope my question is clear. I couldn't find anything on the internet, since I'm a beginner and I don't really understand everything in React. I worked with other JS things before, but this is completely new.
thank you for your question. Nick Parsons answer is correct but if you're still struggling to implement this I have created an example in this Sandbox: https://codesandbox.io/s/kind-surf-y9t4ce?file=/src/App.js
Apologies if I have misunderstood some of the variable names and what the functions are meant to do my (I assume) German? isn't great.
Essentially all I have done is created a couple of functions in your app.js and passed them as props to your bookTile.js with a couple of parameters to the functions to so we can console log those. This means we can reuse the same function multiple times rather than creating unique functions that do the same thing for every book we might be showing.
For real apps we might get 1000+ books that we want to show so creating things reusable in this way is better than creating thousands of functions.
Feel free to ask any follow up questions from my example - I'm happy to try and answer those.

HTML Within Loop Not Rendering in React

I'm attempting to list queried posts in the DOM using Gatsby. The small snippet below should suffice because the Graphql query is correctly fetching data. This snippet is within the component, which is also rendering correctly. I'm new to Gatsby and React, and I hope I'm missing something pretty basic.
<div className="container">
Hello! // Renders
{newsItems.map(newsItem => {
console.log(newsItem.context.id); // Logs each news item id to console correctly
Hello! // Does not render
<p>{newsItem.context.id}</p> // Does not render
})}
</div>
You've used curly braces, so this is how you return component from map function.
{newsItems.map(newsItem => {
console.log(newsItem.context.id); // Logs each news item id to console correctly
return (
<>
Hello!
<p>{newsItem.context.id}</p>
</>
)
})}
Haven't tried this, but it should work. This also only works if newsItems contains values. React Fragments <>...</> were used because return must only return single component. You could also use <div>...</div> instead of fragment.
Try this.

Best way to include custom react components between strings/p-tags?

tldr: New to frontend. Trying to include custom components within p-tags for a website, I've tried various methods but can't seem to get it to work unless I hard code the content into the return bit in my react component - this isn't viable as I would like to have many p-tags which would change on my website when a user presses next.
Hi everyone! I'm new to front end programming, and this is my very first question, so please excuse any incorrect terminology and/or question formatting!
I'm currently working on a react project where I have created custom components to include in my webpage. These components work when placed between p-tags.
For example, I made a custom component and it works as expected when I do something like:
function test{
return(
<p>Hello! This is a <ShowDefinition word="website"/> which I made using react! </p>
)}
However, I intend to have lots of content which would change using an incremental index, so I've placed my content in a separate jsx file to store as a dictionary.
I found that when doing something like this:
function test{
return(
<div>{script[index].content}</div>
)};
where
script[index].content = '<p>Hello! This is a <ShowDefinition word="website"/> which I made using react! </p>';
it just shows up as a string literal on the webpage. I've tried to wrap my string in {} but this did not seem to work.
I've also tried dangerouslySetInnerHTML with a dompurification to sanitise the html code
dangerouslySetInnerHTML={{__html: DOMPurify.sanitize(script[index].content)}};
This worked however it excluded all of my custom components. So for the example sentence it would show up on the page as "Hello! This is a which I made using react!"
I understand now this doesn't work because dangerouslySetInnerHTML cannot convert custom components/only accepts html, however I am now at a complete lost as to what to do.
I have thought of storing the content in a md file then parsing it however I have little knowledge of md files/md parsers and from what I've found I don't think solves my problem?
Any advice would be greatly appreciated.
Thank you so much.
Ok, so first of all, this is definitely not how you should think when playing with React. Even if this is technically possible with things like React.createElement or dangerouslySetInnerHTML, I suggest you look at this first. I will help you get the thinking in react.
However if I had to do this in React, I would probably use a custom hooks or any conditional logic to render my jsx.
codesandbox
import "./styles.css";
import React from "react";
const useContentFromIndex = (index) => {
return () => {
if (index === 0) return <p> Index 0 </p>;
if (index === 1) return <p> Index 1 </p>;
return <p> Index 2 </p>;
};
};
export default function App({ index = 0 }) {
const CustomContent = useContentFromIndex(index);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<CustomContent />
</div>
);
}

Refactoring logic outside of Context.Consumer

To get my desired behavior I ended up nesting ternarys inside of my Context.Consumer and it looks pretty ugly.
I have tried refactoring out some of the logic, but I have been unable to get rerenders to trigger when the props/state change unless I use Context.Consumer.
Working on an app for a project. It uses SWAPI to search for pretty much anything in the Star Wars universe. I have a that changes depending on the user's input, and then loads the results of their search.
I started out just trying to get the results to render after the fetch finished and was having some issues of handling the props/state update of the component not triggering a re-render. We recently learned about React's Context api so I decided to try using that in this simple project even though it's 100% not necessary. I did some reading and ended up with the Context.Consumer. It works great for what I want, and triggers re-renders when I need it to.
render() {
return (
<AppContext.Consumer>
// value here is: characterData: this.state.characterData from App.js
// characterData is in App.js' state and is updated after the fetch is successful.
{value => (
<section className="results-container" style={this.styles}>
{/* FIX refactor this \/ */}
{/*
If they haven't searched for anything, characterData doesn't exist yet,
well it's an empty {object} so it renders the 'Enter a name and hit submit!'
If they search and the results are empty, it tells them to try another name.
If the search works it renders the results.
*/}
{value.characterData.results ? (
value.characterData.results.length > 0 ? (
value.characterData.results.map(item => (
<p style={this.styles} key={item.url} className={item.index}>
{item.name ? item.name : item.title}
</p>
))
) : (
<span>Coulnd't find anything! Try another name or topic.</span>
)
) : (
<span className="default-results-text">
Enter a name and hit submit!
</span>
)}
{/* FIX refactor this /\ */}
</section>
)}
</AppContext.Consumer>
);
}
I am not getting any errors, just trying to figure out a way to clean this up.
When trying to move logic outside the Context.Consumer I have to fall back to using state/props and then it never rerenders.
I've tried using componentWillReceiveProps() and static getDerivedStateFromProps() but again couldn't get rerenders to trigger.
Hosted on Zeit: https://starwars-search-nm7mk0268.now.sh/
I ended up refactoring all of the logic to the parent component and just returning the value of all the logic. This allowed me to get away from nested ternarys and clean up this component's render method

Unable To Access Nested JSON Data from React Component

I have a map function that renders JSON data retrieved like this:
<div className="items">
{items.map(item =>
<Card key={item.id} price={item.title} />)}
</div>
It successfully iterates over and renders data from un-nested properties, but I am having trouble getting it to render the USD nested prop as shown here:
"price":{
"amounts":{
"GBP":"£8,185",
"USD":"$12,000",
"EUR":"€10.755"
},
I am trying to extract it like this:
<div className="items">
{items.map(item =>
<Card key={item.id} price={item.price.amounts.USD} />)}
</div>
And the error message I'm getting is "TypeError: Cannot read property 'amounts' of null." I have also tried with square brackets to no success.
As you mentioned in comments, some of the price values are null (all the item doesn't contains the price object), thats why it is throwing error:
Cannot read property 'amounts' of null.
Solution is, put the check before accessing the amount property, Like this:
price={item.price? (item.price.amounts||{}).USD||0 : 0}
Although the answer above is 100% correct (and recommended) I would consider using _.get if you are already using lodash:
import get from 'lodash/get'
// in render
// the third argument is the default price is *any* of the path is not defined
price={ get(item, 'price.amounts.USD', 0) }
For me, the pathing system in lodash (get, has, set) are extremely expressive and result in much more readable code. If you are importing just get (using the above import, instead of import { get } from lodash) the size footprint is also quite small.
Update:
An interesting comment by #SimianAngel - 100% correct regarding the default value. 0 is probably not what you want as a default value! Depending on your business logic of course.
Again leveraging the path methods of lodash, creating something readable and expressive is quite simple:
import get from 'lodash/get'
import has from 'lodash/has'
// in render
<div>
{has(item, 'price.amounts.USD'))
? <Card key={item.id} price={get(item, 'price.amounts.USD'} />
: <div>This item isn't available in this region</div>
}
</div>

Categories

Resources