I have a search result component that contains a div that, when clicked, is supposed to open a modal. Here's the relevant code below:
const createClickableDiv = function(props){
if(props.searchType === 'option1'){
return (
<div onClick={this.onDivClick}>
<div>Some content</div>
</div>
);
}else if(props.searchType === 'option2'){
return (
<div onClick={this.onDivClick}>
<div>Some other content</div>
</div>
);
}
return (<div className="result-empty"></div>);
};
class SearchResultItem extends Component{
constructor(props){
super(props);
}
onDivClick(){
AppUIActions.openModal((<Modal />));
}
render(){
const clickableDiv = createClickableDiv(this.props);
return (
<div>
{clickableDiv}
</div>
}
}
When I load the page, nothing shows up. However, when I remove onClick={this.onDivClick} from the divs, everything renders correctly, just without the desired click functionality. I put a try-catch around the code in the createClickableDiv function and it's saying this is undefined. I'm not really sure where to go from here.
Thanks!
this. sometimes behaves strangely. When your function createClickableDiv is called, this no longer refers to your SearchResultItem but to the createClickableDiv, which does not have the function onDivClick defined.
Try changing the function call to createClickableDiv(this), to pass pointer to your complete SearchResultItem,
and change the function itself to:
const createClickableDiv = function(caller){
if(caller.props.searchType === 'option1'){
return (
<div onClick={caller.onDivClick}>
<div>Some content</div>
</div>
// etc..
Maybe that would work.
Related
I want to display a specific number of components around a component. How can I do that? :)
With this implementation, I draw 8 Patrat component
{Array.from(Array(8)).map((item, index) =>
(<Patrat key={index}/>)
)}
I want to display these 8 Patrat around a circle which is also a component.
After Understanding the issue and what you want here is the final solution
You can also create function which can dynamically create position and pass it to the Child components
Here is complete code resource link (Click Here)
Also your can experiment with some comment line in code link given above
You could create a recursive loop where you create a new Patrat component with the recursive call as children to it.
Example
function Patrat({ children }) {
return (
<div
style={{
paddingLeft: 10,
backgroundColor: "#" + Math.floor(Math.random() * 16777215).toString(16)
}}
>
{children}
</div>
);
}
function App() {
const content = (function patratLoop(num) {
if (num === 0) {
return <div> Foo </div>;
}
return <Patrat>{patratLoop(--num)}</Patrat>;
})(8);
return content;
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
You could make the circle responsible for positioning the elements, then have Patrats as children of circle (Circle > div.circle_element_position > Patrat) or if Patrats will change depending on the parent component, you could use same logic but use renderProps for Patrats (Circle > div.circle_element_position > props.renderPatrat(index))
It would look more or less like this:
function Partat() {
return <div>1</div>
}
function calculatePositions(numberOfPatrats) {
//your implementation
}
function Circle ({numberOfPatrats}) {
let positions = calculatePositions(numberOfPatrats);
return <div className="circle">
{positions.map(
(position, index) => <div style={position} key={index}><Partat /></div>
)}
</div>
}
To place Parats on the positions you want you just need to implement calculatePositions, which will be similar to what you had in your jsfiddle example.
I am having trouble reading the margin-right css property of the body. It seems to fail on initial render, but a few times it seemed to work when I was manually setting the margin-right. I expect it has something to do when when the component is rendering. Tried in useEffect and useLayoutEffect without success.
Pertinent CSS:
body {
margin-right: 10px;
}
Simple create-react-app:
function App() {
const [marginRight, setmarginRight] = useState(
document.body.style.marginRight
);
return (
<div className="App">
<p>BODY Right margin is: {marginRight}</p>
</div>
);
}
HTMLelement.style only returns inline styles. To access style from your css file, you should use:
window.getComputedStyle(document.body).marginRight
I've recently started trying to use react-virtualized, but I've ran into an issue from the get-go. I've been trying to build a very simple grid, at first I loaded my data in and it wasn't working properly, but I've changed it to a simple 4x4 Grid and it's still giving me issues. Right now all 16 cells are being loading in a single column, and I've tried logging the rowIndex and the columnIndex, and those are giving me the correct output.
I'm not sure if I'm doing something wrong when I call the Grid, or if I'm doing something wrong with the cellRenderer, I would really appreciate some help with this. I have parts of my code down below.
_cellRenderer({columnIndex, key, rowIndex, styles}){
return(
<div>
{columnIndex}
</div>);
}
render(){
return(
<div>
<Autosizer>
{({width}) => (
<Grid
cellRenderer={this._cellRenderer}
columnCount={4}
columnWidth={30}
rowCount={4}
rowHeight={30}
width={400}
height={400}
/>
)}
</Autosizer>
</div>
);
}
You aren't using the parameters passed to your renderer. For example, style and key are both passed for a reason and you must use them. (The documentation should make this pretty clear.)
Put another way:
// Wrong:
function cellRenderer ({ columnIndex, key, rowIndex, style }) {
return (
<div>
{columnIndex}
</div>
)
}
// Right:
function cellRenderer ({ columnIndex, key, rowIndex, style }) {
return (
<div
key={key}
style={style}
>
{columnIndex}
</div>
)
}
Also, in case you didn't notice, the parameter is style and not styles like your code snippet shows.
I am using
console.log("+++++++++++++++++++++++++", document.getElementById("liqcont").attributes);
before the return{} part of a .tsx file.
Typescript is returning an error
TS2531: Object is possibly null.
I need the style properties of the liqcont div to see what class properties have been actually rendered. Any other way to do that?
You can try using refs, and then in componentDidMount get all attributes of that element with the ref. Something like this should work :
class Test extends React.Component {
componentDidMount(){
let attributes = this.refs["wrapper"].attributes;
}
render(){
return (
<div ref="wrapper">
........
</div>
)
}
}
React.render(<Test />, document.getElementById('container'));
Hope this helps.
I have a scrollspy directive that adds an ".active" class to a nav item. When the first nav item has the ".active" class I want my header bar to contain a certain class too. Attached is a simplified example, but how can I add ".active" to item 1 by only looking at the classes in item 2. jsfiddle
<div ng-app>
<div ng-controller='ctrl'>
<div id="item1" ng-class="if item2 has class=active then add active class here">Item 1</div>
<div id="item2" ng-class="myVar">Item 2</div>
</div>
//I can't use a scope object I can only look at item 2's classes
<button type="button" ng-click="myVar='active'">Add Class</button>
<button type="button" ng-click="myVar=''">Remove Class</button>
Click here for live demo.
You'll need a directive to interact with the element. I would have the directive watch the element's classes and have it call a function from your controller when the classes change. Then, your controller function can apply the logic specific to your need, which is to set a flag letting another element know how to respond.
angular.module('myApp', [])
.controller('MyCtrl', function($scope) {
$scope.foo = function(classes) {
if (~classes.indexOf('active')) {
$scope.otherItemIsActive = true;
}
};
})
.directive('onClassChange', function() {
return {
scope: {
onClassChange: '='
},
link: function($scope, $element) {
$scope.$watch(function() {
return $element[0].className;
}, function(className) {
$scope.onClassChange(className.split(' '));
});
}
};
})
;