Do React console warnings need to be dealt with before deploying? - javascript

I've been learning to code for about 3 months now and I've gotten pretty far with an APP I created but when I inspect the page, I have over 50 warnings. Here are some of the warnings
react-dom.development.js:67 Warning: Text content did not match. Server: "Sign out" Client: "Create"
at a
at O (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1647879270456:148896:19599)
at Link (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1647879270456:89219:19)
THERE ARE BOUT 10 LINKS SIMILAR TO THE ONES ABOVE THAT FOLLOW
VM2101 react_devtools_backend.js:3973 Warning: Each child in a list
should have a unique "key" prop.
Check the render method of AllAssets. See
https://reactjs.org/link/warning-keys for more information.
at O (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1647879270456:148896:19599)
at AllAssets (http://localhost:3000/_next/static/chunks/pages/index.js?ts=1647879270456:40:73)
THERE ARE BOUT 10 LINKS SIMILAR TO THE ONES ABOVE THAT FOLLOW
VM2101 react_devtools_backend.js:3973 Warning: The tag is
unrecognized in this browser. If you meant to render a React
component, start its name with an uppercase letter.
at image
at O (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1647879270456:148896:19599)
at span
at O (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1647879270456:148896:19599)
THERE ARE BOUT 10 LINKS SIMILAR TO THE ONES ABOVE THAT FOLLOW
These equal out to about 100 lines of errors all seeming to be referring to the same issues. To be honest, I don't really know how to address tese. Like for example, the one that sasys that all child lists should have a key prop. I'm pretty sure it's referring to some instances where I have the following:
return (
<ul>
{assets.map((result) => {
const {
collection: { name },
data: { image },
} = result;
if (name !== null) {
return (
<Container>
<Card key={name}>
<CollectionAvatar
image={image}
/*name={name || collection}*/
type="collection"
/>
<br></br>
<br></br>
{name}
</Card>
</Container>
);
}
})}
</ul>
);
}
You see, I added a key, but I don't really know if that's the right way to do it or if I added the wrong key etc. I'm still learning about this.
Typing this up I realize that I have a few questions:
Are the errors that I have shown critical? Do they need to be fixed before deploying?
Is there anyway to hide these in the meantime if they are not critical so that I can fix them at a later time?
How can I find out what the error is talking about. I see a link but I don't understand what the result is showing me.
Thanks for you patience. Like I said, I'm learning and I realize I still have a lot to learn but I'd appreciate some clarity on this!

Well, you could deploy your app with warnings. But you should keep in mind that they could lead to unpredictable behaviors in the future, so address them as soon as possible. If I remember correctly, they will still show up the console, but you will be able to deploy the app. It's also worth remembering that some CI servers (like netlify) don't allow you to deploy your app with warnings, so you need to set an environment variable before deploying. (CI=false)
It's hard to know exactly what is the problem in your code just by looking at the logs. But to solve the one related to the keys, you need to pass a unique key as props to the component that is being returned by the map function. So in your case, instead of passing key={name} to the Card component, try passing it to the Container component.

Related

Appears that React is not re-rendering after state update in useeffect (Reask)

Summarize the Problem
Goal
I am attempting to create a cart feature for my Shop Inventory project. This cart will basically contain a list of product ids and eventually allow a user to see all of the items in this 'cart'. Once the user feels like they have added all of the products they'd like to purchase to their cart, they will have a button within the cart page to purchase all products in the cart.
Ideally, I will store a list of product ids in local storage, and once the user navigates to a certain route, I will grab the list from local storage using JSON.parse/JSON.stringify and implement the feature accordingly (Putting the products ids into a state variable called products). It seems to be working fine except for a bit of debugging code I put in place.
Expected VS Actual
I have put this debugging code inside of my component to show me the list of products that have been grabbed from local storage.
{products.map((product) => {
<h2>{product}</h2>;
})
}
However, whenever I load the page the only content I see is more debugging content like "Hello World" I put above it. What I expected to see when I loaded the page was a list of ids that corresponded to the products put into the cart. I know that it had at least one product inside of the 'products' state variable by looking into the react dev tools.
Error Messages
There are no error messages.
Describe what you've tried
Debugging attempts
React Dev Tools
I was able to confirm that even though the state variable list isn't being displayed, the state variable itself is getting updated. I was able to verify this with the React Dev Tools.
VS Debugger
I also attempted to look through the debugger before and after the state had been set. The array I set it to seems to be correct:
I noticed that after going through quite a bit of the internal workings of React it came back to my code inside of useEffect. And when it did the products state variable was updated correctly. However, in the next few steps I took with the debugger, it didn't seem to go back to my visual part to re-render it.
Stack Overflow
I have searched through some Stack Overflow questions that popped up while asking this question. I believe the closest question is this one which hasn't been answered yet. Some of them are troubles with working with child components and directly accessing the state variable instead of using set both of which I am not doing. For the child issues, the major one I looked at was this one. For the directly accessing this is the major one.
Show some code
Cart.js
Using a functional react component, I have a 'products' state variable that I attempt to populate in the useEffect hook with a certain key in local storage. Below is my Cart component. You may notice there is also another state variable called 'addingResource' which is used to indicate if the Cart component has been created to add a resource to the cart or to simply display it. As you can see as well the addingResource state variable gets updated in the useEffect hook. I'm not entirely sure if that is possibly what is affecting the products state variable, but I figured I would note it here in case it is. Once again the main problem is that the products map function inside of the return statement does not show any items, even after the products state variable appears to be updated.
function Cart(props) {
const [products, setProducts] = React.useState([]);
const [addingResource, setAddingResource] = React.useState(false);
const REACT_APP_CART_TOKEN_NAME = process.env.REACT_APP_CART_TOKEN_NAME;
// Ensures that addingResource is updated to true if needed
React.useEffect(() => {
if (props.match && addingResource === false) {
setAddingResource(true);
}
const stringVersion = window.localStorage.getItem(
REACT_APP_CART_TOKEN_NAME
);
let productIdsList = [];
if (stringVersion) {
productIdsList = JSON.parse(stringVersion);
console.log("test");
}
if (props.match) {
productIdsList.push(props.match.params.id);
window.localStorage.setItem(
REACT_APP_CART_TOKEN_NAME,
JSON.stringify(productIdsList)
);
}
alert("Updating Products");
if (!products) {
setProducts(productIdsList);
}
}, []);
// TODO: Read the products key from the local storage
return (
<>
<h1>Match: {`${addingResource}`}</h1>
{products &&
products.map((product) => {
<h2>{product}</h2>;
})}
</>
);
}
Local Storage 'Cart' Token
Additionally, the 'cart' local storage token that is being accessed in this component has this structure:
[
'5fccb14ed0822f25ec5cee63'
]
Finishing Remarks
This is a recreated question from my originally closed question you can find here. I believe the reason it was closed is that I was having problems submitting my question. There appeared to be a section of code that stack overflow said was invalid. I had looked through all of the code segments I had put in and none of them seemed off. I even tried formatting the spacing in a text editor and pasting it over a few times to make sure it had the right spacing. I even removed all of the code snippets and tried to submit it that way. However, it still told me there was an error somewhere in my post. I then tried to use the process of elimination to resolve this issue by slowly removing sections of my post and trying to submit it. The problem this caused was that my initial posting had only a slight portion of the original post. I was trying to quickly find the error and fill in the rest of the information. I was able to eventually able to find the section of text near my "React Dev Tools" paragraph that was causing this error. After resolving this error, I was able to submit my post in its complete form. Unfortunately, it seems that my question was closed and even after adding some additional details to my original lengthy post and putting a section is asking the person who closed the question to review it again and message me if anything was wrong, it remained closed for nearly a week. Because of this, I decided to make a new post ensuring all of my original post's content was available from the first version.
I greatly appreciate any help and hope to resolve this issue for me and those in the future that come across this. Thank you!
Your useEffect looks ok. But you need to return a value inside your map function, else it won't display anything :
return (
<>
{products.map(product => <h2>{product}</h2>)}
</>
);
When you remove the braces around the content of an arrow function, it is considered as the returned value. Else, you can simply write () => { return <>blabla</> });

Isolating components from integrated app code in React

I'm looking for help isolating out components from my body of code. I can't figure out how to link the input and output variables that are currently integrated throughout the app code. I've tried pulling out short parts of rendered html(/jsx) and helper functions, but so far no luck. (this is a requirement for a training program.)
My approach has been to cut and paste the desired segment into a new javascript file, replace in the app function with a component call to the new js file (via exporting from component, importing in app), replace the object variable in the component with a simple abstract name (e.g., change "task" to "object") and establish equivilancies in the component call. However, I can't get this to work -- when I remove the original variables and replace with component calls, everything else stops recognizing their variables.
So I'm looking for advice and help on how to make components of the sections detailed below. Sorry if this is vague without the specific error messages and an entire detailing of my approaches so far -- I figure there is something I'm fundamentally missing about how to isolate components from the code I currently have -- All the information I've found that should be relevant relies on props to be attached to property variables in the app component, which is not how I have my app coded. I'm hoping I don't have to gut my code and start over.
To begin with, this is the smallest contained code, the basic content of the html:
//ListItem
<li
key={listItem.index}
onClick={() => {
handleClick(listItem.index);
}}
> {listItem.string}
</li>
after that would be its container element:
//Div
<div>
<h2>w/e</h2>
<ul>
{list
.map((item, index) => ({ ...item, index }))
.filter((item) => item.position === "right")
.map((listItem) => (
<ListItem props.../> // the ListItem component defined before
))}
</ul>
</div>
so that finally, i would have:
<body><Div props... /></body>
the last thing I'm trying to seperate as a component is an object array being used to set state via useState:
//Tasks
//const [list, setList] = useState(
[
{ string: "string", position: "position" } //and many more
]);
For each piece of the code that you extract, ask yourself "what information does this code need to render?" The answer to that question becomes your props. A ListItem needs key, onClick, and its contents. You can pass the contents as a string property, or you can make use of props.children.
Not every single JSX element needs to be its own component. Think about which chunks of code change depending on the variables of your app. Those variables become props and those code chunks become components.

Passing props and mapping data in React

I'm working on a project that requires me to pass data to two functional components.
My axios call to the API seems to work, as well as setting the state with hooks, but I keep receiving these two errors:
Error Cannot convert undefined or null to object I tried checking if the array is empty but that didn't seem to solve the problem
summaryMetrics is not defined - This I don't understand because summartMetrics is defined. Could it be that the elements are being displayed before the data is fetched ?
Here are the files in a codesandbox
Included the API's so people can see the structure of how the JSON is being returned.
Im not sure if I'm passing and mapping the data correctly.
Here are the files in a codesandbox
Any help is very much appreciated
Since your state has this form :
const [summary, setSummaryData] = useState({
summaryMetrics: null,
platformsData: null
});
...you should access your state like this :
<SummaryMetrics
uniqueSocialMediaPost={summary.summaryMetrics[0]["uniqueSocialMediaPost"]}
positiveScore={summary.summaryMetrics[0]["positiveScore"]}
riskScore={summary.summaryMetrics[0]["riskScore"]}
/>
[...]
Note the "summary." before "summaryMetrics" :
summary.summaryMetrics[0]["uniqueSocialMediaPost"]
Fixed Fixed Code Sandbox (other things seems to go wrong though, white screen, but syntax error is fixed) :
Previous errors were :
mocky.io serves content over HTTP, Code Sandbox over HTTPS so mixed content issue : Chrome does not allow this kind of mix in protocols, fixed by using HTTPS protocol to grab infos from mocky.io,
no unique keys for SummaryByPlatform component in map function
Chrome dev tools is your friend when nothing happens as expected :).
By the way you could just
summary.summaryMetrics.map(s => <SummaryByPlatform summaryMetrics={s} />)
...instead of gettings keys, and you could simply pass whole summaryMetrics object to SummaryByPlatform and have only one props. But that's another subject.
Good luck with it.
Your issue is that you're not waiting for summaryMetrics to load. It's trying to read the array before it's been fetched.
What I would do, is put the render inside a function and conditionally load it once the data is available.
So your Summary.js file would look like this:
const renderSummaryMetrics = () =>
summary &&
summary.summaryMetrics && (
<div>
<SummaryMetrics
uniqueSocialMediaPost={summary.summaryMetrics[0]["uniqueSocialMediaPost"]}
positiveScore={summary.summaryMetrics[0]["positiveScore"]}
riskScore={summary.summaryMetrics[0]["riskScore"]}
/>
{Object.keys(summary.summaryMetrics) &&
Object.keys(summary.summaryMetrics).length > 0
? Object.keys(summary.summaryMetrics).map(keyName => (
<SummaryByPlatform
platform={keyName}
mean_sentiment={summary.summaryMetrics[keyName].mean_sentiment}
post_count={summary.summaryMetrics[keyName].post_count}
positive_posts={summary.summaryMetrics[keyName].positive_posts}
negative_posts={summary.summaryMetrics[keyName].negative_posts}
/>
))
: null}
</div>);
return renderSummaryMetrics();
There are several problems:
summaryMetrics is indeed not defined. It was actually defined as summary.summaryMetrics.
summary.summaryMetrics[0][...] will cause another "undefined error", because it was defined with default value of null.
Explanation for Problem 1:
No further explanation needed.
Explanation for Problem 2:
useEffect in React functional component will only be run after the component is being rendered.
This means that when you execute summary.summaryMetrics[0][...], summary.summaryMetrics is actually null because you defined it as the default value. Therefore, the steps behind will generate another error because null[0] is not possible.
What you need to do is to check whether each object properties down the tree is actually a valid object before you call the property. Otherwise, the error will happen down the property tree.
I can't show you how to correct your code, because I would need to change a big part of you code. What you can try is to mainly check the presence of values of summary.summaryMetrics first, before calling it's children properties.

When doing role based routing in react, is use of switch statement and showing different component based on role a security issue?

I have the following code, its simple and does the job. But is there security issues with this? This is my first time doing role based authorization so trying to understand what I can do better.
<Route path={"/"} component={RootPage}></Route>
export default const RootPage({role}) => {
switch(role) {
case USER: return <MainPageUser />
case ADMIN: return <AdminPage />
default: return <MainPage />
}
}
There are a few options you can choose from, all of them are (almost) just as (un)safe as the other. It's javascript, if someone wants to, then can change it as it's client side.
You can do the switch as you are doing, or something like:
{role==="admin" && <AdminStuff />} // the component only gets rendered if the first part is true
{role==="user" && <UserStuff />} // so in this case it's one or the other.
You can also create a component thats called a voter:
function RoleVoter({grantedRole, requiredRole, children){
render(){
return grantedRole===requiredRole ? children : null;
}
}
// Example:
<RoleVoter grantedRole={role} requiredRole={ADMIN}> <AdminStuff/> </RoleVoter>
Each varies in complexity and usability, they all have their benefits/drawback. The switch is usefull if "only one case may match". The && method is good for quick coding, but will result in hardcoding very fast, hard to maintain. The RoleVoter aproach is more complex and might be overkill, but you can now throw every role in there you want. And expand it to understand multiple roles (eg ADMIN and VIEW_ORDERS if you want that kind of level of security).
All of these are about as safe as the other. It's Javascript, at happens clientside, nothing you can do about that. What is more important, is that you pick a solution which is easy to implement/understand by the developers. The reason for that is that the easier security becomes to implement, the more often you will implement it.
Then where lies the real security? Easy: Serverside. Imagine you hack some javascript and you get it to show you an admin page, but the server never gave it the actual content. Pretty useless. You also create the security checks serverside based on the current user.
A somewhat standard method is that you make voters (small functions) that each test two things:
Can the user add/view/edit/delete this type of item (in general)? E.g. does the user have EDIT_USER permission when trying to edit a user? Or a VIEW_ORDER when trying to view an order?
Can the user add/view/edit/delete this specific item? E.g. if you can only change an order when it's your own, is it actually yours?

How can I make my React child components render even if a prop is missing

TLDR; I need to be able to render child components in React even if a property of this.props is missing.
I have an React app built with Yahoo's Flxubile. The app fetches data from a Wordpress site with WP REST API. Sometimes an image might be missing or something else from the API, this causes the client to break. Here's an example:
I have a file called Articles.js which is connected to ArticlesStore which holds my articles. I then render one Article.js for every article I have and pass props like this:
{ this.props.articles.map(function(el, index) {
return <Article key={index} article={el} />
})
}
Everything is ok here, but then in my Article.js when I try to access properties that is not set I get the following:
Uncaught TypeError: Cannot read property 'sizes' of undefined
This is the line which causes the error:
<img src={this.props.article.meta_fields.image.sizes.large} />
This happens when a image is missing from an article. I understand the javascript error of course but I want to render the Article.js component event if a image url is missing from the API/Store. I have tried the following solutions, but it causes too much clutter and no control:
Conditional set if we have the prop i.e.
{this.props.article.meta_fields.image ? this.props.article.meta_fields.image.sizes.large : "imagemissing.png"}
Setting defaultProps. This does not work because passed properties from parent to child overwrites defaultProps.
Maybe I should try something else than passing props from parent to child? Have a ArticleStore where I can set default values for every article? How would you do it?
If you want to provide a nested structure as a prop (as with article) you'll want to be able to rely on the structure always being pretty much the same. In this case it won't be, sometimes the meta_fields does not have an image-attribute (as your TypeError suggests).
In your case I would consider pulling out the things you actually need/use in the Article component from the article object and pass those as props.
Say that your Article only uses title, body, and image. Then just pass those as props.
<Article title={ article.title } body={ article.body } image={ getImage(article) }/>
function getImage(article) {
if (article.meta_fields.image
&& article.meta_fields.image.sizes
&& article.meta_fields.image.sizes.large
) {
return article.meta_fields.image.sizes.large;
}
return 'default_image.jpg'; // Or whatever you want.
}
One might think that the extra props constitutes more "clutter" here, but given the choice between clutter and TypeError, I choose clutter.
And if you don't want to reinvent the wheel. The problem of accessing data in a nested structure like this have been solved before.
// Lodash
_.get(article, 'meta_fields.image.sizes.large', 'default_image.jpg')
// Ramda
_.pathOr('default_image.jpg', ['meta_fields', 'image', 'sizes', 'large'], article)

Categories

Resources