I have someone who is responsible for opening / closing the window, I am trying to have one of the three gifts displayed randomly when opened. While there is no progress, how can I do this.
I understand that I need to do this through state.random, but now I don’t understand how. Apparently I'm completely blond ))))
// start open box
var TOGGLE_BOX = '[GiftBox] Toggle';
var toggleBox = function () {
return { type: TOGGLE_BOX };
};
//REDUCERS (Update)
var DEFAULT = { open: false, wasOpen: false };
var reducer = function (state, action) {
if (state === void 0) {state = DEFAULT;}
switch (action.type) {
case TOGGLE_BOX:{
return {
open: state.open ? false : true,
wasOpen: state.open };
}
default:return state;}
};
var store = Redux.createStore(reducer, DEFAULT);
var mapStateToProps = function (state) {
return { open: state.open, wasOpen: state.wasOpen };
};
var mapDispatchToProps = function (dispatch) {
return { dispatch: dispatch };
};
var cGiftBox = function (_a) {
var wasOpen = _a.wasOpen,open = _a.open,dispatch = _a.dispatch;
return React.createElement("div", { className: "floor" },
React.createElement("div", { className: "box" },
open ?
React.createElement("button", { className: "heart-gift", }, "gift1") :
React.createElement(React.Fragment, null),
React.createElement("div", { className: open ?
'lid open' :
wasOpen ?
'lid close' :
'lid', onClick: function (e) {return dispatch(toggleBox());} },
React.createElement("div", { className: "qcube" }, open ? '!' : '?'),
React.createElement("div", { className: "face ltop" }),
React.createElement("div", { className: "face lleft" }),
React.createElement("div", { className: "face lright" })),
React.createElement("div", { className: "face top" }),
React.createElement("div", { className: "face left" }),
React.createElement("div", { className: "face right" }),
));
};
// connect and render
var Provider = ReactRedux.Provider,connect = ReactRedux.connect;
var GiftBox = connect(mapStateToProps, mapDispatchToProps)(cGiftBox);
ReactDOM.render(React.createElement(Provider, { store: store },
React.createElement(GiftBox, null)), document.getElementById('root'));
Related
First time poster so let me know if more information is need.
Trying to figure out why my global state using context API is being updated even when my setSate method is commented out. I thought i might have been mutating the state directly accidently but I dont believe I am
"specialModes" in actionOnClick() is the state in question
const SpecialFunctions: FC = (props: Props) => {
const { currentModeContext, specialModesContext: specialActionsContext, performCalc, inputValueContext } = useContext(AppContext)
const { specialModes, setSpecialModes } = specialActionsContext
const { currentMode, setCurrentMode } = currentModeContext
const { inputValue, setInputValue } = inputValueContext
const categoryOnClick = (index: number) => {
setCurrentMode(specialModes[index])
console.log(specialModes[index].title);
}
const actionOnClick = (action: IAction) => {
let newAction = action
newAction.value = performCalc()
let newSpecialModes = specialModes.map((mode) => {
if (mode === currentMode) {
let newMode = mode
newMode.actions = mode.actions.map((element) => {
if (element === action) {
return newAction
}
else return element
})
return newMode
}
else return mode
})
//setSpecialModes(newSpecialModes)
}
let headings = specialModes.map((categorgy, index) => {
return <Heading isActive={categorgy === currentMode ? true : false} onClick={() => categoryOnClick(index)} key={index}>{categorgy.title}</Heading>
})
let actions = currentMode.actions.map((action, index) => {
return (
<Action key={index} onClick={() => actionOnClick(action)}>
<ActionTitle>{action.title}</ActionTitle>
<ActionValue>{action.value}</ActionValue>
</Action>
)
})
return (
<Wrapper>
<Category>
{headings}
</Category>
<ActionsWrapper toggleRadiusCorner={currentMode === specialModes[0] ? false : true}>
{actions}
</ActionsWrapper>
</Wrapper>
)
}
Context.tsx
interface ContextType {
specialModesContext: {
specialModes: Array<ISpecialModes>,
setSpecialModes: React.Dispatch<React.SetStateAction<ISpecialModes[]>>
},
currentModeContext: {
currentMode: ISpecialModes,
setCurrentMode: React.Dispatch<React.SetStateAction<ISpecialModes>>
},
inputValueContext: {
inputValue: string,
setInputValue: React.Dispatch<React.SetStateAction<string>>
},
inputSuperscriptValueContext: {
inputSuperscriptValue: string,
setInputSuperscriptValue: React.Dispatch<React.SetStateAction<string>>
},
performCalc: () => string
}
export const AppContext = createContext({} as ContextType);
export const ContextProvider: FC = ({ children }) => {
const [SpecialModes, setSpecialModes] = useState([
{
title: 'Rafter',
actions: [
{
title: 'Span',
active: false
},
{
title: 'Ridge Thickness',
active: false
},
{
title: 'Pitch',
active: false
}
],
},
{
title: 'General',
actions: [
{
title: 'General1',
active: false
},
{
title: 'General2',
active: false
},
{
title: 'General3',
active: false
}
],
},
{
title: 'Stairs',
actions: [
{
title: 'Stairs1',
active: false
},
{
title: 'Stairs2',
active: false
},
{
title: 'Stairs3',
active: false
}
],
}
] as Array<ISpecialModes>)
const [currentMode, setCurrentMode] = useState(SpecialModes[0])
const [inputValue, setInputValue] = useState('0')
const [inputSuperscriptValue, setInputSuperscriptValue] = useState('')
const replaceCharsWithOperators = (string: string): string => {
let newString = string.replaceAll(/\s/g, '') // delete white space
newString = newString.replace('×', '*')
newString = newString.replace('÷', '/')
console.log(string)
console.log(newString)
return newString
}
const performCalc = (): string => {
let originalEquation = `${inputSuperscriptValue} ${inputValue} =`
let equation = inputSuperscriptValue + inputValue
let result = ''
equation = replaceCharsWithOperators(equation)
result = eval(equation).toString()
setInputSuperscriptValue(`${originalEquation} ${result}`)
setInputValue(result)
console.log(result)
return result
}
return (
<AppContext.Provider value={
{
specialModesContext: {
specialModes: SpecialModes,
setSpecialModes: setSpecialModes
},
currentModeContext: {
currentMode,
setCurrentMode
},
inputValueContext: {
inputValue,
setInputValue
},
inputSuperscriptValueContext: {
inputSuperscriptValue,
setInputSuperscriptValue
},
performCalc
}}>
{children}
</AppContext.Provider>
)
}
In your mode.actions.map() function you are indirectly changing actions field of your original specialModes array.
To fix this problem you need to create shallow copy of specialModes array Using the ... ES6 spread operator.
const clonedSpecialModes = [...specialModes];
let newSpecialModes = clonedSpecialModes.map((mode) => {
// rest of your logic here
})
I'm trying to create a certain functionality in my react-data-grid.
I have a column called subStart, and I have a dropdown that I want to use so that the user can set the value of a cell to the value of a state variable (this.state.timeTotalSec).
So if the user clicks on "Use Global Time" option in a 'Start Time' cell, it will replace the value of that cell with the value of this.state.timeTotalSec. How on earth do I do this?
I have the dropdown functionality working. But how do I get it to change the cell value?
const rows = [
{ id: 1, subStart: "00:00.000", subEnd: "00:00.000" , subText: 'Text1'},
{ id: 2, subStart: "00:00.000", subEnd: "00:00.000" , subText: 'Text2'},
{ id: 3, subStart: "00:00.000", subEnd: "00:00.000" , subText: 'Text3'}
];
const columns = [
{
key: "id",
name: "ID"
},
{
key: "subStart",
name: "Start Time",
editable: true
},
{
key: "subEnd",
name: "End Time",
editable: true
},
{
key: "subText",
name: "Text",
editable: true
}
].map(c => ({ ...c, ...defaultColumnProperties }));
const subStartActions = [
{
icon: <span className="glyphicon glyphicon-remove" />,
callback: () => {
alert("Deleting");
}
},
{
icon: "glyphicon glyphicon-link",
actions: [
{
text: "Use Global Time",
callback: () => {
// TODO
// **** TRYING TO MAKE THIS WORK ****
}
}
]
}
];
function getCellActions(column, row) {
const cellActions = {
subStart: subStartActions
};
return row.id % 2 === 0 ? cellActions[column.key] : null;
}
const ROW_COUNT = 50;
class App extends React.Component {
constructor (props) {
super(props)
this.state = {
playing: false,
duration: 0,
timeMilli: 0,
timeSec: 0,
timeMin: 0,
timeTotalSec: 0,
rows
}
}
onDuration = (duration) => {
this.setState({ duration })
}
onProgress = (progress) => {
if (this.state.duration == 0) {
return
}
const timeTotalSec = progress.played * this.state.duration
if (timeTotalSec !== this.state.timeTotalSec) {
const timeMin = Math.floor(timeTotalSec / 60)
const timeSec = Math.floor(timeTotalSec - (timeMin)*60)
const timeMilli = (timeTotalSec - timeSec - timeMin*60).toFixed(3)
this.setState({ timeTotalSec })
this.setState({ timeMin })
this.setState({ timeSec })
this.setState({ timeMilli })
}
}
onGridRowsUpdated = ({ fromRow, toRow, updated }) => {
this.setState(state => {
const rows = state.rows.slice();
for (let i = fromRow; i <= toRow; i++) {
rows[i] = { ...rows[i], ...updated };
}
return { rows };
});
};
render () {
const { data } = this;
return (
<div className='player-wrapper'>
<ReactPlayer
url='https://www.youtube.com/watch?v=lhlZkqEag7E'
className='react-player'
playing={this.state.playing}
onPlay={() => this.setState({ playing: true })}
onPause={() => this.setState({ playing: false })}
controls='True'
onDuration={this.onDuration}
onProgress={this.onProgress}
/>
Video is currently: {this.state.playing ? 'playing' : 'paused'}
<br />
Duration: {Math.round(this.state.duration).toString() + ' seconds'}
<br />
Elapsed: {this.state.timeMin + 'min ' + this.state.timeSec + 'sec ' +
this.state.timeMilli + 'ms'}
<br />
<button onClick={() => this.setState({ playing: true })}>Play</button>
<button onClick={() => this.setState({ playing: false })}>Pause</button>
<ButtonToolbar>
<Button variant="primary" onClick={() => this.setState(this.state.playing ? false : true)}>Play/Pause</Button>
</ButtonToolbar>
<ReactDataGrid
columns={columns}
rowGetter={i => this.state.rows[i]}
rowsCount={ROW_COUNT}
// minHeight={500}
getCellActions={getCellActions}
onGridRowsUpdated={this.onGridRowsUpdated}
enableCellSelect={true}
/>
</div>
)
}
}
ReactDataGrid will just render what data you pass to it, If you want to change the value of a cell, you should update the rows from data source or state you are using.in your case rows
this.state = {
playing: false,
duration: 0,
timeMilli: 0,
timeSec: 0,
timeMin: 0,
timeTotalSec: 10,
rows // your datasourse
};
I've supposed,id is your data Key.Add updateRowDate to actions to handle your state changes.
actions: [
{
text: "Use Global Time",
callback: () => {
// TODO
// **** TRYING TO MAKE THIS WORK ****
updateRowDate(row.id);
}
}
]
and here is updateRowDate in App component
updateRowDate = rowId => {
this.setState(prv => ({
rows: prv.rows.map(q => {
if (q.id === rowId) return { ...q, subStart: this.state.timeTotalSec };
return q;
})
}));
finally, you need to pass updateRowDate to getCellActions
<ReactDataGrid
columns={columns}
rowGetter={i => this.state.rows[i]}
rowsCount={ROW_COUNT}
// minHeight={500}
getCellActions={(column, row) =>
getCellActions(column, row, this.updateRowDate)
}
onGridRowsUpdated={this.onGridRowsUpdated}
enableCellSelect={true}
/>
Here is the temporary sandbox containing the fixed version
Main app:
class App extends Component {
constructor(props) {
super(props);
this.state = {
totalCheckBoxes: 0,
checkboxesClicked: 0,
percentage: 0,
};
this.checkboxClick = this.checkboxClick.bind(this);
}
checkboxClick(type) {
(type) ? this.setState({ checkboxesClicked: checkboxesClicked++ }) :
(type > 0) ? this.setState({ checkboxesClicked: checkboxesClicked-- }) : this.setState({ checkboxesClicked: 0 });
}
render() {
// grab steps
const { steps } = this.props;
const { totalCheckBoxes } = this.state;
const { checkboxClick } = this;
// add rendered steps to .allTheSteps
return (
ce('div', { className:'allTheSteps' },
ce(pagination, { steps }),
Object.values(steps).map((step, i) =>
ce(Steps, { step, key: v4(), i, checkboxClick }),
)
)
);
};
};
Child component:
const Steps = ({ step, i, checkboxClick }) =>
ce( "div", {
className: `mainBoxes clearfix playbook_step_${i}`,
key: v4(),
},
ce('span', {
className: 'steps'
}, step.id + 1 + ' - '),
ce("strong", {
className: "titleText",
key: v4(),
}, step.name),
( step.summary.length ) ? ce('div', { className: 'step__summary' }, step.summary) : null,
ce( "div", {
className: "stepArticle__content",
key: v4(),
},
step.articles.map(({ name, url }, j) => ce(Articles, { name, url, key: v4(), j, checkboxClick }))
)
);
Grandchild component:
class Articles extends Component {
constructor(props) {
super(props);
this.state = {
notes: false,
questions: false,
};
this.addNotes = this.addNotes.bind(this);
this.askQuestions = this.askQuestions.bind(this);
}
addNotes() {
this.setState({ notes: !this.state.notes });
}
askQuestions() {
this.setState({ questions: !this.state.questions });
}
render(){
const { name, url, checkboxClick } = this.props;
const { notes, questions } = this.state;
const { addNotes, askQuestions } = this;
return ce('div', null, Article( { name, url, notes, questions, addNotes, askQuestions, checkboxClick } ));
}
}
const Article = ({ name, url, notes, questions, addNotes, askQuestions, checkboxClick }) => (
ce('div', { className: 'stepArticle step__'},
ce('div', {className: 'clearfix'},
ce('div', {className: 'articleTitle'},
ce('input', {
type: 'checkbox',
name: 'done',
onClick: checkboxClick.bind(null, this),
className: 'checkBoxes'}
),
ce('a', {
className: 'checkLink',
target: '_blank',
href: url
}, name),
),
ce('div', {className: 'articleActions'},
ce('input', {
type: 'button',
value: 'Make Notes',
className: 'addNotes',
onClick: addNotes,
}),
ce('input', {
type: 'button',
value: 'Ask Clausehound',
className: 'askQuestions',
onClick: askQuestions,
}),
)
),
(notes) ? ce('textarea', {
className: 'text_areas notes notes__',
placeholder: 'My Notes: '
}) : null,
(questions) ? ce('textarea', {
className: 'text_areas questions questions__',
placeholder: 'Questions for Clausehound Research Team: ',
}) : null,
)
);
The app is a step by step instruction/tutorial and when a user is done with a step, they tick the checkbox and a percentage for completion is displayed. I want to calculate the percentage of checkboxes that have been clicked.
Currently I am trying to do this in checkboxClick function in the parent component. Is this the correct approach? The type needs to be a boolean so that we know whether a checkbox was checked or unchecked.
Codesandbox link.
I am learning ReactJS. I wrote a web app that should show an input text and a button 'Confirm', and when pressed it shows a second input text with a button 'Go back' which removes the new input. When the second one is showed, the first input and the first button are disabled.
However, my current script is not accepted. I'm having problems with passing functions as prop to the function FormRender and with indicating in the FormRender object itself the property "disabled" (it claims to have found "unexpected token").
Are there any better approaches?
function FormRender (props) {
return (
<div>
<input type = "text" placeholder = {this.props.holder} {this.props.disable} />
<button onClick = {this.props.Click()} {this.props.disable} > {this.state.value} </button>
</div>
);
};
var R = React.createClass ({
getInitialState: function () {
return { names: [], disable: false }
},
update: function () {
return this.state.disable ? "disabled" : "";
},
componentDidMount: function () {
var a = this.state.names;
a.push ( <FormRender holder = 'Name' value = 'Confirm' Click = {this.In}, disable: {this.update} /> );
this.setState ( { names: a } );
this.forceUpdate();
},
In: function () {
var a = this.state.names;
this.setState ( { disable: true } );
a.push ( <FormRender holder = 'Surname ' value = 'Back' Click = {this.Out} disable: "" /> );
this.setState ( { names: a } );
this.forceUpdate();
},
Out: function () {
var a = this.state.names;
this.setState ( { disable: false } );
a.splice(a.length-1,1);
this.setState ( { names: a } );
this.forceUpdate();
},
render: function () {
return (
<div>
{this.state.names}
</div>
);
}
});
I am not sure if it is what you want my example
function FormRender (props) {
return (
<div>
<input
type="text"
placeholder={props.holder}
disabled={props.disable()}
/>
<button
onClick={props.click}
disabled={props.disable()}
>
{props.value}
</button>
</div>
);
};
var R = React.createClass ({
getInitialState: function () {
return {names: [], disable: false}
},
update: function () {
return this.state.disable;
},
componentDidMount: function () {
var a = this.state.names;
var form = {
holder: 'Name',
value: 'Confirm',
click: this.In,
disable: this.update
};
a.push(form);
this.setState({names: a});
},
In: function () {
if (this.state.names.length > 1) {
return;
}
var a = this.state.names;
var form = {
holder: 'Surname',
value: 'Back',
click: this.Out,
disable: function () {
return false
}
}
this.setState({disable: true});
a.push(form);
this.setState({names: a});
},
Out: function () {
var a = this.state.names;
this.setState({disable: false});
a.splice(a.length-1,1);
this.setState({names: a});
},
render: function () {
return (
<div>
{this.state.names.map(function (el) {
return (<FormRender
holder={el.holder}
value={el.value}
click={el.click}
disable={el.disable}
/>);
})}
</div>
);
}
});
https://jsfiddle.net/69z2wepo/72509/
You have got many syntax errors in you code.
I recommend use linter :)
I have build a component using material ui default components. It is a menu. I want to close this menu once the user clicks anywhere outside the menu.
How can I do it? Icon Menu does that. When you click anywhere else on body the menu closes but the Menu component does not do so. After looking into Icon Menu code i have noticed how it renders Menu Component with some changes but could not locate the function which triggers close on click outside body.
Below is the code for Icon Menus
const React = require('react');
const ReactDOM = require('react-dom');
const ReactTransitionGroup = require('react-addons-transition-group');
const ClickAwayable = require('../mixins/click-awayable');
const StylePropable = require('../mixins/style-propable');
const Events = require('../utils/events');
const PropTypes = require('../utils/prop-types');
const Menu = require('../menus/menu');
const DefaultRawTheme = require('../styles/raw-themes/light-raw-theme');
const ThemeManager = require('../styles/theme-manager');
const IconMenu = React.createClass({
mixins: [StylePropable, ClickAwayable],
contextTypes: {
muiTheme: React.PropTypes.object,
},
propTypes: {
closeOnItemTouchTap: React.PropTypes.bool,
iconButtonElement: React.PropTypes.element.isRequired,
iconStyle: React.PropTypes.object,
openDirection: PropTypes.corners,
onItemTouchTap: React.PropTypes.func,
onKeyboardFocus: React.PropTypes.func,
onMouseDown: React.PropTypes.func,
onMouseLeave: React.PropTypes.func,
onMouseEnter: React.PropTypes.func,
onMouseUp: React.PropTypes.func,
onTouchTap: React.PropTypes.func,
menuStyle: React.PropTypes.object,
style: React.PropTypes.object,
touchTapCloseDelay: React.PropTypes.number,
},
getDefaultProps() {
return {
closeOnItemTouchTap: true,
openDirection: 'bottom-left',
onItemTouchTap: () => {},
onKeyboardFocus: () => {},
onMouseDown: () => {},
onMouseLeave: () => {},
onMouseEnter: () => {},
onMouseUp: () => {},
onTouchTap: () => {},
touchTapCloseDelay: 200,
};
},
//for passing default theme context to children
childContextTypes: {
muiTheme: React.PropTypes.object,
},
getChildContext () {
return {
muiTheme: this.state.muiTheme,
};
},
getInitialState () {
return {
muiTheme: this.context.muiTheme ? this.context.muiTheme : ThemeManager.getMuiTheme(DefaultRawTheme),
iconButtonRef: this.props.iconButtonElement.props.ref || 'iconButton',
menuInitiallyKeyboardFocused: false,
open: false,
};
},
//to update theme inside state whenever a new theme is passed down
//from the parent / owner using context
componentWillReceiveProps (nextProps, nextContext) {
let newMuiTheme = nextContext.muiTheme ? nextContext.muiTheme : this.state.muiTheme;
this.setState({muiTheme: newMuiTheme});
},
componentWillUnmount() {
if (this._timeout) clearTimeout(this._timeout);
},
componentClickAway() {
this.close();
},
render() {
let {
className,
closeOnItemTouchTap,
iconButtonElement,
iconStyle,
openDirection,
onItemTouchTap,
onKeyboardFocus,
onMouseDown,
onMouseLeave,
onMouseEnter,
onMouseUp,
onTouchTap,
menuStyle,
style,
...other,
} = this.props;
let open = this.state.open;
let openDown = openDirection.split('-')[0] === 'bottom';
let openLeft = openDirection.split('-')[1] === 'left';
let styles = {
root: {
display: 'inline-block',
position: 'relative',
},
menu: {
top: openDown ? 12 : null,
bottom: !openDown ? 12 : null,
left: !openLeft ? 12 : null,
right: openLeft ? 12 : null,
},
};
let mergedRootStyles = this.prepareStyles(styles.root, style);
let mergedMenuStyles = this.mergeStyles(styles.menu, menuStyle);
let iconButton = React.cloneElement(iconButtonElement, {
onKeyboardFocus: this.props.onKeyboardFocus,
iconStyle: this.mergeStyles(iconStyle, iconButtonElement.props.iconStyle),
onTouchTap: (e) => {
this.open(Events.isKeyboard(e));
if (iconButtonElement.props.onTouchTap) iconButtonElement.props.onTouchTap(e);
},
ref: this.state.iconButtonRef,
});
let menu = open ? (
<Menu
{...other}
animated={true}
initiallyKeyboardFocused={this.state.menuInitiallyKeyboardFocused}
onEscKeyDown={this._handleMenuEscKeyDown}
onItemTouchTap={this._handleItemTouchTap}
openDirection={openDirection}
style={mergedMenuStyles}>
{this.props.children}
</Menu>
) : null;
return (
<div
className={className}
onMouseDown={onMouseDown}
onMouseLeave={onMouseLeave}
onMouseEnter={onMouseEnter}
onMouseUp={onMouseUp}
onTouchTap={onTouchTap}
style={mergedRootStyles}>
{iconButton}
<ReactTransitionGroup>{menu}</ReactTransitionGroup>
</div>
);
},
isOpen() {
return this.state.open;
},
close(isKeyboard) {
if (this.state.open) {
this.setState({open: false}, () => {
//Set focus on the icon button when the menu close
if (isKeyboard) {
let iconButton = this.refs[this.state.iconButtonRef];
ReactDOM.findDOMNode(iconButton).focus();
iconButton.setKeyboardFocus();
}
});
}
},
open(menuInitiallyKeyboardFocused) {
if (!this.state.open) {
this.setState({
open: true,
menuInitiallyKeyboardFocused: menuInitiallyKeyboardFocused,
});
}
},
_handleItemTouchTap(e, child) {
if (this.props.closeOnItemTouchTap) {
let isKeyboard = Events.isKeyboard(e);
this._timeout = setTimeout(() => {
this.close(isKeyboard);
}, this.props.touchTapCloseDelay);
}
this.props.onItemTouchTap(e, child);
},
_handleMenuEscKeyDown() {
this.close(true);
},
});
module.exports = IconMenu;
This behavior is given by the ClickAwayable mixin you can find the source here
Simply import (or require) it in your custom component and add a componentClickAway method that will trigger the close of your menu.
const ClickAwayable = require('material-ui/lib/mixins/click-awayable')
const CustomMenu = React.createClass({
mixins: [ClickAwayable],
componentClickAway () {
// close your menu
}
})