function generateTargets() { return _.times(1000, (i) => { return { id: i, x: Math.random() * window.innerWidth, y: Math.random() * window.innerHeight, radius: 2 + Math.random() * 5, color: Konva.Util.getRandomColor() }; }); } // // "UPDATE", function appReducer(state, action) { if (action.type === 'UPDATE') { const i = _.findIndex(state.targets, (t) => t.id === action.id); const updatedTarget = { ...state.targets[i], radius: action.radius }; state = { targets: [ ...state.targets.slice(0, i), updatedTarget, ...state.targets.slice(i + 1) ] } } return state; } const initialState = { targets: generateTargets() }; // const store = Redux.createStore(appReducer, initialState);
function Target(props) { const {x, y, color, radius} = props.target; return ( <Group x={x} y={y}> <Circle radius={radius} fill={color} /> <Circle radius={radius * 1 / 2} fill="black" /> <Circle radius={radius * 1 / 4} fill="white" /> </Group> ); } // class App extends React.Component { constructor(...args) { super(...args); this.state = store.getState(); // subscibe to all state updates store.subscribe(() => { this.setState(store.getState()); }); } render() { const targets = this.state.targets.map((target) => { return <Target key={target.id} target={target}/>; }); const width = window.innerWidth; const height = window.innerHeight; return ( <Stage width={width} height={height}> <Layer hitGraphEnabled={false}> {targets} </Layer> </Stage> ); } }
const N_OF_RUNS = 500; const start = performance.now(); _.times(N_OF_RUNS, () => { const id = 1; let oldRadius = store.getState().targets[id].radius; // redux store.dispatch({type: 'UPDATE', id, radius: oldRadius + 0.5}); }); const end = performance.now(); console.log('sum time', end - start); console.log('average time', (end - start) / N_OF_RUNS);
class Target extends React.Component { shouldComponentUpdate(newProps) { return this.props.target !== newProps.target; } render() { const {x, y, color, radius} = this.props.target; return ( <Group x={x} y={y}> <Circle radius={radius} fill={color} /> <Circle radius={radius * 1 / 2} fill="black" /> <Circle radius={radius * 1 / 4} fill="white" /> </Group> ); } }
class Target extends React.Component { constructor(...args) { super(...args); this.state = { target: store.getState().targets[this.props.index] }; // subscibe to all state updates this.unsubscribe = store.subscribe(() => { const newTarget = store.getState().targets[this.props.index]; if (newTarget !== this.state.target) { this.setState({ target: newTarget }); } }); } shouldComponentUpdate(newProps, newState) { return this.state.target !== newState.target; } componentWillUnmount() { this.unsubscribe(); } render() { const {x, y, color, radius} = this.state.target; return ( <Group x={x} y={y}> <Circle radius={radius} fill={color} /> <Circle radius={radius * 1 / 2} fill="black" /> <Circle radius={radius * 1 / 4} fill="white" /> </Group> ); } }
shouldComponentUpdate(newProps, newState) { // - // id , "" const changed = newState.targets.find((target, i) => { return this.state.targets[i].id !== target.id; }); return changed; }
const {Stage, Layer, Circle, Group} = ReactKonva; const {observable, computed} = mobx; const {observer} = mobxReact; class TargetModel { id = Math.random(); @observable x = 0; @observable y = 0; @observable radius = 0; @observable color = null; constructor(attrs) { _.assign(this, attrs); } } class State { @observable targets = []; } function generateTargets() { _.times(1000, (i) => { state.targets.push(new TargetModel({ id: i, x: Math.random() * window.innerWidth, y: Math.random() * window.innerHeight, radius: 2 + Math.random() * 5, color: Konva.Util.getRandomColor() })); }); } const state = new State(); generateTargets(); @observer class Target extends React.Component { render() { const {x, y, color, radius} = this.props.target; return ( <Group x={x} y={y}> <Circle radius={radius} fill={color} /> <Circle radius={radius * 1 / 2} fill="black" /> <Circle radius={radius * 1 / 4} fill="white" /> </Group> ); } } @observer class App extends React.Component { render() { const targets = state.targets.map((target) => { return <Target key={target.id} target={target}/>; }); const width = window.innerWidth; const height = window.innerHeight; return ( <Stage width={width} height={height}> <Layer hitGraphEnabled={false}> {targets} </Layer> </Stage> ); } } ReactDOM.render( <App/>, document.getElementById('container') );
Source: https://habr.com/ru/post/304340/
All Articles