calling props within state React - reactjs

I'm trying to create a changeLanguage feature for my React Website. When a language ("English" or "Spanish") is selected it is passed down to all components in a props.language . When these props are received I want my components to print out text in the language indicated by the props. I have written the text in the state of the component one in Spanish and another in English. When my component renders I want it to print the right state according to what props are passed down. Any help?

You've messed up the syntax. Use this: <h4>{ this.state[this.props.language].title }</h4>

If you have multiple languages, send an object as your variable for every entity you wish to translate before hand. For example your page title may be
let greeting = {"English":"Hello","Spanish":"Hola"}
Then inside your render, you would have:
<div className="title">{this.state[this.props.language].greeting}</div>

Related

Problem using Trans Component with two or more links in text i18next

I'm pretty stuck. I am trying to insert a text that contains two links with the Trans component. I'm using a function instead of a class, because I can't figure out how to use the hook in a class.
The codeI am trying is:
<Trans i18nKey={text} t={t} components={links} />
Where text is the id and links is this: [</>, </>], and the function receives links from props. If I type components=[</>, </>] directly (no props) it works fine (on json, i am using <0></0> and <1></1>. I really don't know how render a text with two or more links inside...

React don't mount component until needed but don't unmount afterwards in list of components

Say I am building an instant messaging with app with React (I'm not doing that exactly, but this is easier to explain). I have a sidebar with a list of conversations and, when you click one, it is shown on the right (similar to this). I don't want to mount each conversation component until the user clicks it, but I don't want to unmount it, just hide it, when they click on another conversation. How can I do this cleanly? There will never be more than about 30 chats for any user.
You can store the enabled conversations in an array that you use to show, and when you disable a conversation you can just add a hidden prop to it which you pass to the conversation and make it return null. This will make it not render anything but will not unmount it since you have not removed it from the array that handles the display of conversations.
example at: https://codesandbox.io/s/wispy-forest-59bqj
This is a bit hard to answer since you haven't posted the code.
But, theoretically, the best way to approach this problem is to transfer the data from your sidebar component and load it onto the right component on a per-user basis. You don't have to mount each "conversation component".
You can do this by with the boolean hidden property in your markup. React will render as usual and simply pass it along to the html, the browser will then simply not paint it.
const HideMe = ({ isHidden }) => (
<div hidden={isHidden}>
can you see me?
</div>
)
I made an example for you:
https://codesandbox.io/s/elastic-curie-t4ill?file=/src/App.js
reference: https://www.w3schools.com/tags/att_hidden.asp

cannot render a complex React Element in order to replace a DOM element by id

I am a beginner with react so please excuse me if this question does not make sense.
I have a complex div element in the html document with an id, it looks like this:
aaavote: I am comingChange My voteDelete Me
and it was originally created from rendering a react element that was returned from a component, like this:
let content = visitors_list.map((visitor) =>
)
{content} was returned from the react component.
At some stage I need to replace that div (with id="MyDiv2") with a different content.
I have a function that creates this new "content" exactly the same way I created the original one, however, now instead of return it from the component and have react do the rendering, I need to do it manually and call:
document.getElementById("MyDiv2").innerHTML = something
I cannot just pass content as something because : component is an array of [object Object]
I cannot pass it as a json structure because JSON.stringify(content) gives me:
[{"type":"div","key":"1","ref":null,"props":{"className":"flex-no-shrink w-full md:w-1/4 md:px-3","children":{"key":null,"ref":null,"props":{"visitor":{"id":"1","name":"aaa","vote":0,"imageUrl":"http://www.stone-guitar-picks.com/stoneguitarpicksshop/images/large/GP2046_LRG.JPG"}},"_owner":null,"_store":{}}},"_owner":null,"_store":{}}]
so I tried: ReactDOM.render(content, document.getElementById("MyDiv2"))
but ReactDOM.render does nothing, infact it breaks and exists the function.
I also tried using React.createElement(content) - also did not work...
How can I solve this problem. the only solution that I found to work is forcing the refreshing of the page which I do not want to do.
Dont try to handle the dom manually, react does this for you!, imagine you have your component MyInput that renders an input with some characteristics that may be passed by properties as well, then you could just change your component props and react will change your component automatically. i'll try to post a hardcoded example:
const myComp = ({text, visible}) = return (
<input text={text} visibility={visible}>
)
then, when you change your component text it will render it automatically.

How to assign different values to 2 of the same child components in React

For example
I have a parent component named . This component contains 2 of the same components called . it looks like this so far
<Overview>
|<Stats>
|<Stats>
The Stats component contains html that looks like this.
Pic of Stats Component
Now the first time I insert <Stats> I want to assign values different from when I insert the second component. So in the screenshot there are numbers under each section. That is going to be the default numbers every time you insert the <Stats> component. How can I assign different numbers to every time I insert a <Stats> Component. I don't want the same numbers.
What I thought about doing was creating States in overview , for example Submitted, Redeemed...etc. Then in the component retrieve those states but assign itself new values. I have read setState needs to be used but for the life of me I cant figure it out.
Any Help would be greatly appreciated.
You can pass the numbers as props. Just give it a name, assign to that name in your opening JSX tag, and then reference it as this.props.yourPropName in the class. (If you are using classes) or props.yourPropName if the component is made with a function)
function Stats(props){
//your code
}
<Stats yourPropOne=5 yourPropTwo=3/>

ReactJS issue on my test app

So, I've been working through my first ReactJS app. Just a simple form where you type in a movie name and it fetches the data from IMDB and adds them as a module on the page. That's all working fine.
However each movie module also had a remove button which should remove that particular module and trigger a re-render. That's not working great as no matter which button you click it always removes the last movie module added rather than the one you're clicking on.
App:
http://lukeharrison.net/react/
Github codebase:
https://github.com/WebDevLuke/React-Movies
I'm just wondering if anybody can spot the reasoning behind this?
Cheers!
Just a hunch, but you should use a unique key, not just the index of the map function. This way React will understand that the movies are identified not by some iterating index, but an actual value, and that will probably solve your issue.
var movies = this.state.movies.map(function(movie, index){
return (
<Movie key={movie} useKey={index} removeMovieFunction={component.removeMovie} search={movie} toggleError={component.toggleError} />
);
});
This is because React re-evaluates your properties, sees that nothing has changed, and just removes the last <Movie /> from the list. Each Movie's componentDidMount function never runs more than once, and the state of Movie 1, Movie 2 and Movie 3 persists. So even if you supply search={movie} it doesn't do anything, because this.props.search is only used in componentDidMount.
I'm not exactly sure why it isn't rendering correctly as the dataset looks fine.
Looking at the code, I would change your remove function to this...
var index = this.state.movies.indexOf(movieToRemove);
console.log(this.state.movies);
if (index > -1) {
this.state.movies.splice(index, 1);
}
console.log(this.state.movies);
this.setState(this.state.movies);
My assumption is that, the state isn't being updated correctly. Whenever updating state, you should always use setState (unless the convention changed and I wasn't aware).
Also, you shouldn't need to explicitly call forceUpdate. Once setState is called, React will automatically do what it needs to and rerender with the new state.
State should be unidirectional (passed top down) from your top level component (known as a container). In this instance, you have state in your top level component for search strings and then you load individual movie data from within the "Movie" component itself via the IMDB API.
You should refactor your code to handle all state at the top level container and only pass the complete movie data to the dumb "Movie" component. all it should care about is rendering what you pass in it's props and not about getting it's own data.

Resources