Access to a several elements through one ref React - javascript

I wanna get access to multiple elements with using refs feature. Then after I could iterate through elements of this.tabs. Code below doesn't work, how fix it to make work? Solution, which I use now is document.querySelectorAll('tabs'), but it doesn't seems right for React.
class Comp extends React.Component {
constructor(props) {
super(props);
this.tabs = React.createRef();
}
componentDidMount() {
console.log(this.tabs);
}
render() {
return (
<div>
<span class="tab" ref={this.tabs}>One</span>
<span class="tab" ref={this.tabs}>Two</span>
<span class="tab" ref={this.tabs}>Three</span>
</div>
);
}
}
ReactDOM.render(
<Comp />,
document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

You're assigning refs incorrect way. Do it in the early beginning of render() method:
this.tabs = []
refs are going to be assigned via
<span className="tab" ref={(tab) => { this.tabs.push(tab) }}>One</span>
I hope you could call this.tabs this case!

Related

In ReactJS, How do I update child states from parent class?

Here is the parent class
class Root extends React.Component {
constructor(props) {
super(props);
this.state = {
word: Words,
};
}
changeTheWord(i) {
this.state.word.changeWord(i);
}
render() {
return (
<div className="game">
<ul>
<li><a href="#" onClick={() => this.changeTheWord('hey')}>Home</a></li>
<li>News</li>
<li>Contact</li>
<li>About</li>
</ul>
<this.state.word />
</div>
);
}
}
And here is the child class
class Words extends React.Component {
constructor(props) {
super(props)
this.state = {
data: "read"
}
}
changeWord(i) {
this.state.data = i;
}
render() {
var sentence = "testing";
if (this.state.data != null) {
sentence = this.state.data;
}
return (
<div class="center">
<div class="words">
<p>{sentence}</p>
</div>
</div>
);
}
}
What I am trying to do, is call the child's changeWord method from the parent class Root, but for some reason it doesn't work and React gives me an error, TypeError: this.state.word.changeWord is not a function.
This it the line responsible for calling the function
<li><a href="#"onClick={ () => this.changeTheWord('hey')}>Home</a></li>
How do I approach this problem?
You are using React's logic somehow wrong. Why do you want to keep a whole React component (child here) in your state and mutate it with complex and confusing methods? React's logic is very simple and clean. Use state and props, render child components and pass those to it where necessary. Before going any further I strongly suggest reading the basic documentation.
Probably you want to do something like this.
class Parent extends React.Component {
constructor( props ) {
super( props );
this.state = {
data: "default sentence",
};
}
changeTheWord = ( i ) => {
this.setState( { data: i } );
}
render() {
return (
<div className="game">
<Child sentence={this.state.data} changeTheWord={this.changeTheWord} />
</div>
);
}
}
const Child = props => (
<div>
<ul>
<li>
<a href="#" onClick={() => props.changeTheWord( "hey" )}>
Home
</a>
</li>
<li>
News
</li>
<li>
Contact
</li>
<li>
About
</li>
</ul>
{props.sentence}
</div>
);
ReactDOM.render( <Parent />, document.getElementById( "root" ) );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
In your example, the word state property is initialized with the class Words, not an instance of it.
Instead, try initializing your state as follows:
this.state = {
word: new Words()
}

switch components in react js

I'm doing a singlepage application and would like to switch a component.
Here is an image how it looks like:
If I click on the button in component 3, I will switch the component 3 with 5.
So maybe like component 3 is a view of all projects and if I click on one project, I will see a detail view of the project with some information.
I created two different components for this.
All other components should stay at the same place.
Here is my code how I switch the components:
this.state.detailVisible
? <ProjectDetailView/>
: null
I'm not sure if is the correct react way to do it. Also I have two different css files for component 3 and 5. If I'm switching the two component, I have some class name irritations with my css.
If it's a better way to do it with routers?
How is the react way to do it?
thanks for your help :)
It all depends on your needs, if you need to render both component3 and component5 then a route won't be much of a help.
If you need to render only one of them then a route can be handy.
as for the syntax i prefer this:
this.state.detailVisible && <ProjectDetailView/>
here is a simple example:
const components = ["Component1", "Component2", "Component3"];
class Component extends React.Component {
constructor(props) {
super(props);
this.state = {
showDetails: false
};
this.onComponentClicked = this.onComponentClicked.bind(this);
}
onComponentClicked(e) {
this.setState({
showDetails: !this.state.showDetails
});
}
render() {
const { name } = this.props;
const { showDetails } = this.state;
return (
<div>
<div>Component{name}</div>
<button onClick={this.onComponentClicked}>Toggle Details</button>
{showDetails && <ComponentDetails name={name} />}
</div>
);
}
}
const ComponentDetails = ({ name }) => (
<div>
<div>Details of component{name}</div>
</div>
);
class App extends React.Component {
render() {
return (
<div>
<h2>Parent</h2>
{components.map(c => {
return (
<div>
<Component name={c} />
<hr />
</div>
);
})}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

React interract with dom

How can I 'talk' with dom elements with react?
For example - I need to bind some actions with some js lib
Both approaches returns undefined for some reason
componentDidMount() {
const element1 = document.querySelector('.home-container')
const element2 = ReactDOM.findDOMNode(this);
// returns undefined, undefined
console.log(element1.length, element2.length);
}
render() {
return (
<div className="home-container">
...
</div>
)
}
But console.log(element1) returns html from render itself though
How can I work with them?
And what correct lifecycle method for this?
You use "refs":
<div ref={e => {this.div = el}} ...>...</div>
Once your component has rendered, with the above, its div property (you can use any name you want) will refer to the div element that was rendered.
Here's an example largely copied from the link above that focuses a text input when it's rendered:
class AutoFocusTextInput extends React.Component {
componentDidMount() {
this.textInput.focus();
}
render() {
return (
<input type="text"
ref={(input) => { this.textInput = input; }} />
);
}
}
ReactDOM.render(
<AutoFocusTextInput />,
document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Rendering multiple buttons with onClick function in React

I am trying to render multiple buttons in react using map but i am getting an errors.
var NameArray = [{"name":"number0"},{"name":"number1"},{"name":"number2"}];
class RenderButtons extends React.Component {
constructor() {
super();
this.onClick = this.handleClick.bind(this);
}
handleClick(event) {
const {id} = event.target;
console.log(id);
}
render() {
return (
<div>
{NameArray.map((obj, index) =>
<h3 id={index} onClick={this.onClick}>
{obj.name}
</h3>
)}
</div>
);
}
}
ReactDOM.render(
<RenderButtons />,
document.querySelector('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
I am using index as Id for my buttons and NameArray properties as name of the buttons.
I tried spliting render of buttons to new function but i am not sure how to do this.
Apparently you miss # sign in your querySelector function.
document.querySelector('#app');

react fire multiple function in an event

fireOne(){
}
render(){
return(
<p onClick={this.fireOne.bind(this)}></p>
)
}
Can I bind one event with 2 function? one function is for current component, I want to pass something down to the children component as well.
I think this is what you are trying to acomplish, but I'm not completely sure:
class MyComponent extends React.Component {
foo1 = () => { console.log('ahh');}
foo2 = () => { console.log('beh');}
render() {
return(<div onClick={() => {
this.foo1();
this.foo2();
}}>AHH </div>)
}
}
ReactDOM.render(<MyComponent />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"/>

Categories

Resources